前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)


Posted in HTML / CSS onJuly 12, 2018

之前在一个移动端的抽奖页面中,在抽奖结果的展示窗口需要弹幕轮播显示,之前踩过一些小坑,现在总结一下前端弹幕效果的实现方式。

  • css3实现乞丐版的弹幕
  • css3弹幕性能优化
  • canvas实现弹幕
  • canva弹幕的扩展功能

1. css3实现乞丐版的弹幕

(1)如何通过css3实现弹幕

首先来看如何通过css的方法实现一个最简单的弹幕:

首先在html中定义一条弹幕的dom结构:

<div class="block">我是弹幕</div>

弹幕的移动可以通过移动这个block来实现,以从右向左移动的弹幕为例,弹幕的初始位置在容器的最左侧且贴边隐藏(弹幕的最左边与容器的最右贴合),可以通过绝对定位加transform来实现:

.block{
   position:absolute;
}

初始位置:

from{
    left:100%;
    transform:translateX(0)
}

移动到最左边的结束位置为(弹幕的最右边与容器的最左边贴合):

to{
   left:0;
   transform:translateX(-100%)
}

起始位置和结束位置的具体图示如下所示:

前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)

根据起始位置和结束位置可以定义完整的两帧弹幕动画:

@keyframes barrage{
   from{
     left:100%;
     transform:translateX(0);
   }
   to{
     left:0;
     transform:translateX(-100%);
   }
}

给弹幕元素引入这个动画:

.block{
  position:absolute;
  /* other decorate style */
  animation:barrage 5s linear 0s;
}

这样就可以实现一个乞丐版的弹幕效果:

前端实现弹幕效果的方法总结(包含css3和canvas的实现方式) 

(2)通过绝对定位和left实现弹幕的缺陷

首先明确一下css的渲染过程

I)根据HTML的结构生成DOM树(DOM树中包含了display:none的节点) II)在DOM树的基础上,根据节点的几何属性(margin/padding/width/height/left等)生成render树 III)在render树的基础上继续渲染color,font等属性

其中如果I)中和II)中的属性发生变化会发生reflow(回流),如果仅仅III)中的属性发生改变,只会发生repaint(重绘)。显然从css的渲染过程我们也可以看出来:reflow(回流)必伴随着重绘。

reflow(回流):当render树中的一部分或者全部因为大小边距等问题发生改变而需要重建的过程叫做回流 repaint(重绘):当元素的一部分属性发生变化,如外观背景色不会引起布局变化而需要重新渲染的过程叫做重绘

reflow(回流)会影响浏览器css的渲染速度,因此在做网页性能优化的时候要减少回流的发生。

在第一节,我们通过left属性,实现了弹幕的效果,left会改变元素的布局,因此会发生reflow(回流),表现在移动端页面上会造成弹幕动画的卡顿。

2. css3弹幕性能优化

我们直到了第一节中的弹幕动画存在卡顿的问题,下面我们看看如何解决动画的卡顿。

(1)CSS开启硬件加速

在浏览器中用css开启硬件加速,使用GPU(Graphics Processing Unit)可以提升网页性能。鉴于此,我们可以发挥GPU的力量,从而使我们的网站或应用表现的更为流畅。

CSS animations, transforms 以及 transitions 不会自动开启GPU加速,而是由浏览器的缓慢的软件渲染引擎来执行。那我们怎样才可以切换到GPU模式呢,很多浏览器提供了某些触发的CSS规则。

比较常见的方式是,我们可以通过3d变化(translate3d属性)来开启硬件加速,鉴于此,我们修改动画为:

@keyframes barrage{
   from{
     left:100%;
     transform:translate3d(0,0,0);
   }
   to{
     left:0;
     transform:translate3d(-100%,0,0);
   }
}

这样就可以通过开启硬件加速的方式,优化网页性能。但是这种方式没有从根本上解决问题,同时使用GPU增加了内存的使用,会减少移动设备的电池寿命等等。

(2)不改变left属性

第二种方法,就是想办法在弹幕动画的前后不改变left属性的值,这样就不会发生reflow。

我们想仅仅通过translateX来确定弹幕节点的初始位置,但是translateX(-100%)是相对于弹幕节点本身的,而不是相对于父元素,因此我们耦合js和css,在js中获取弹幕节点所在的父元素的宽度,接着根据宽度来定义弹幕节点的初始位置。

以父元素为body时为例:

//css
 .block{
  position:absolute;
  left:0;
  visibility:hidden;
  /* other decorate style */
  animation:barrage 5s linear 0s;
}
//js
let style = document.createElement('style');
document.head.appendChild(style);
let width = window.innerWidth;
let from = `from { visibility: visible; -webkit-transform: translateX(${width}px); }`;
let to = `to { visibility: visible; -webkit-transform: translateX(-100%); }`;
style.sheet.insertRule(`@-webkit-keyframes barrage { ${from} ${to} }`, 0);

除了耦合js计算了父元素的宽度,从而确定弹幕节点的初始位置之外,这里在弹幕节点中我们为了防止初始位置就有显示,增加了visibility:hidden属性。防止弹幕节点在未确定初始位置时就显示在父容器内。只有弹幕开始从初始位置滚动,才会变得可见。

但是这种css的实现方式,在实现弹幕的扩展功能方面比较麻烦,比如如何控制弹幕暂停等等。

3. canvas实现弹幕

除了通过css实现弹幕的方法之外,通过canvas也可以实现弹幕。

通过canvas实现弹幕的原理就是时时的重绘文字,下面来一步步的实现。

获取画布

let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');

绘制文字

ctx.font = '20px Microsoft YaHei';          
    ctx.fillStyle = '#000000';                
    ctx.fillText('canvas 绘制文字', x, y);

上面的fillText就是实现弹幕效果的主要api,其中x表示横方向的坐标,y表示纵方向的坐标,只要时时的改变x,y进行重绘,就可以实现动态的弹幕效果。复制代码

清除绘制内容

ctx.clearRect(0, 0, width, height);

具体实现

通过定时器,定时改变x,y,每次改变之前先进性清屏,然后根据改变后的x,y进行重绘。当存在多条弹幕的情况下,定义:

let colorArr=_this.getColor(color);  弹幕数组多对应的颜色数组
    let numArrL=_this.getLeft();  弹幕数组所对应的x坐标位置数组
    let numArrT=_this.getTop();  弹幕数组所对应的y坐标位置数组
    let speedArr=_this.getSpeed(); 弹幕数组所对应的弹幕移动速度数组

定时的重绘弹幕函数为:

_this.timer=setInterval(function(){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.save();
    for(let j=0;j<barrageList.length;j++){
      numArrL[j]-=speedArr[j];
      ctx.fillStyle = colorArr[j]
      ctx.fillText(barrageList[j],numArrL[j],numArrT[j]);
      ctx.restore();
 },16.7);

实现的效果为:

前端实现弹幕效果的方法总结(包含css3和canvas的实现方式) 

4. canva弹幕的扩展功能

通过canvas实现弹幕的方式,很方便做比如暂停弹幕滚动等扩展功能,此外,也可以给弹幕增加头像,给每条弹幕增加边框等等功能,以后再补充。

最后给一个简单的react弹幕组件;https://github.com/forthealllight/react-barrage

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3+Sprite实现僵尸行走动画特效源码
Jan 27 HTML / CSS
利用纯CSS3实现动态的自行车特效源码
Jan 20 HTML / CSS
HTML5使用ApplicationCache接口实现离线缓存技术解决离线难题
Dec 13 HTML / CSS
HTML5中微数据概述及在搜索引擎中的使用举例
Feb 07 HTML / CSS
HTML5 Canvas渐进填充与透明实现图像的Mask效果
Jul 11 HTML / CSS
HTML5的download属性详细介绍和使用实例
Apr 23 HTML / CSS
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
Aug 31 HTML / CSS
Canvas环形饼图与手势控制的实现代码
Nov 08 HTML / CSS
Canvas波浪花环的示例代码
Aug 21 HTML / CSS
CSS3实现模糊背景的三种效果示例
Mar 30 HTML / CSS
在CSS中映射鼠标位置并实现通过鼠标移动控制页面元素效果(实例代码)
Apr 22 HTML / CSS
使用CSS实现一个搜索引擎的原理解析
Sep 25 HTML / CSS
如何用canvas实现在线签名的示例代码
Jul 10 #HTML / CSS
canvas简易绘图的实现(海绵宝宝篇)
Jul 04 #HTML / CSS
快速实现一个简单的canvas迷宫游戏的示例
Jul 04 #HTML / CSS
HTML5中form如何关闭自动完成功能的方法
Jul 02 #HTML / CSS
Canvas实现保存图片到本地的示例代码
Jun 28 #HTML / CSS
html5手机端页面可以向右滑动导致样式受影响的问题
Jun 20 #HTML / CSS
canvas环形倒计时组件的示例代码
Jun 14 #HTML / CSS
You might like
使用MaxMind 根据IP地址对访问者定位
2006/10/09 PHP
PHP学习之数组的定义和填充
2011/04/17 PHP
解析PHP缓存函数的使用说明
2013/05/10 PHP
php除数取整示例
2014/04/24 PHP
php提取字符串中网站url地址的方法
2014/12/03 PHP
javascript 隔行换色函数代码
2010/10/24 Javascript
jquery 圆形旋转图片滚动切换效果
2011/01/19 Javascript
浅析Node在构建超媒体API中的作用
2014/07/30 Javascript
node.js中的fs.realpath方法使用说明
2014/12/16 Javascript
js计算德州扑克牌面值的方法
2015/03/04 Javascript
jQuery常用样式操作实例分析(获取、设置、追加、删除、判断等)
2016/09/08 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
2017/12/26 Javascript
微信小程序3种位置API的使用方法详解
2019/08/05 Javascript
详解Vue 换肤方案验证
2019/08/28 Javascript
[01:34]2016国际邀请赛中国区预选赛IG战队教练采访
2016/06/27 DOTA
Python的Django框架中TEMPLATES项的设置教程
2015/05/29 Python
Python中列表元素转为数字的方法分析
2016/06/14 Python
Python将list中的string批量转化成int/float的方法
2018/06/26 Python
django用户登录验证的完整示例代码
2019/07/21 Python
python实现多进程通信实例分析
2019/09/01 Python
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
2019/12/12 Python
python模块和包的应用BASE_PATH使用解析
2019/12/14 Python
解决pycharm安装第三方库失败的问题
2020/05/09 Python
python实现猜单词游戏
2020/05/22 Python
HTML5 DeviceOrientation实现手机网站摇一摇功能代码实例
2015/04/24 HTML / CSS
Html5 webview元素定位工具的实现
2020/08/07 HTML / CSS
出门问问全球官方商城:Tichome音箱和TicWatch智能手表
2017/12/02 全球购物
屈臣氏官方旗舰店:亚洲享负盛名的保健及美妆零售商
2019/03/15 全球购物
Servlet如何得到客户端机器的信息
2014/10/17 面试题
岗位职责定义及内容
2013/11/08 职场文书
搞笑创意广告语
2014/03/17 职场文书
房产转让协议书(2014版)
2014/09/30 职场文书
2015学校年度工作总结
2015/05/11 职场文书
单身证明范本
2015/06/15 职场文书
python实现股票历史数据可视化分析案例
2021/06/10 Python
动画「半妖的夜叉姬」新BD特典图公开
2022/03/22 日漫