侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

前端  /  管理员 发布于 7年前   260

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

  • 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%)}

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

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

@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;}

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

 

(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;}//jslet 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);

实现的效果为:

 

4. canva弹幕的扩展功能

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

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

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


  • 上一条:
    CSS background-position的使用说明详解
    下一条:
    HTML5中使用json对象的实例代码
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客