当前位置: 首页 > Web前端 > CSS

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

时间:2023-03-30 18:45:26 CSS

之前在移动端的一个开奖页面,需要在开奖结果的展示窗口中弹幕轮播展示.之前踩过一些小坑,现在总结一下前端弹幕效果的实现。css3实现乞丐版弹幕css3弹幕性能优化canvas实现弹幕canvas的扩展功能Canva弹幕先来看看如何通过css实现最简单的弹幕:首先在html中定义一个弹幕的dom结构:我是弹幕

弹幕可以移动是通过移动这个方块来实现的。以从右向左移动的弹幕为例。弹幕的初始位置在容器的最左侧,隐藏边缘(弹幕的最左侧与容器的最右侧对齐)。通过绝对定位和变换实现:.block{position:absolute;}initialposition:from{left:100%;transform:translateX(0)}移动到最左边的结束位置(弹幕的最右边和容器的最左边合):to{left:0;transform:translateX(-100%)}开始位置和结束位置的具体说明如下:根据开始位置和结束位置,可以定义一个完整的两帧弹幕动画:@keyframes弹幕{from{left:100%;变换:翻译X(0);}到{左:0;变换:翻译X(-100%);}}给弹幕元素引入这个动画:.block{position:absolute;/*otherdecoratestyle*/animation:barrage5slinear0s;}这样就可以实现一个乞丐版的弹幕效果:(2)绝对定位左移实现弹幕的缺陷首先明确一下渲染过程cssI)根据HTML结构生成DOM树(DOM树包含节点display:none)II)在DOM树的基础上,根据节点的几何属性(margin/padding/width/height/left等)III)在渲染树的基础上继续渲染颜色、字体等属性。如果I)和II)中的属性发生变化,就会发生回流(reflow)。如果只有III)中的属性发生变化,则只会发生重绘。重的Drawing)显然我们从css的渲染过程中也可以看出:回流(reflow)必然伴随着重绘。回流(reflow):当渲染树的一部分或全部由于大小和边距的变化需要重新构建时,称为回流repaint(重绘):当元素的部分属性发生变化时,比如外观背景色不会导致布局改变而重新渲染的过程称为重绘回流(reflow),会影响浏览器css的渲染速度,所以在优化网页性能的时候,减少回流的发生。在第一节中,我们通过left属性实现了弹幕的效果。Left会改变元素的布局,所以会出现回流(reflow),也就是弹幕动画会卡在手机页面。2.CSS3弹幕性能优化我们在第一节就来到了弹幕动画问题。让我们看看如何解决动画卡顿。(1)使用CSS启用硬件加速使用CSS在浏览器中启用硬件加速,使用GPU(GraphicsProcessingUnit)提高网页性能。鉴于此,我们可以借助GPU的强大功能,让我们的网站或应用程序运行得更加流畅。CSS动画、变换和转换不会自动启用GPU加速,而是由浏览器的缓慢软件渲染引擎执行。那么我们如何切换到GPU模式呢?许多浏览器提供了某些触发CSS规则。更常见的方式是我们可以通过3d变化(translate3d属性)来启用硬件加速。鉴于此,我们将动画修改为:@keyframes弹幕{from{left:100%;变换:translate3d(0,0,0);}到{左:0;变换:translate3d(-100%,0,0);}}这样就可以通过开启硬件加速来优化网页的性能。但是这种方法并没有从根本上解决问题,使用GPU反而增加了内存占用,降低了移动设备的电池寿命等等。(2)不改变left属性第二种方法是想办法在弹幕动画前后不改变left属性的值,这样就不会发生回流。我们只想通过translateX来确定弹幕节点的初始位置,但是translateX(-100%)是相对于弹幕节点本身的,而不是相对于父元素的,所以我们耦合js和css在js中获取弹幕节点所在父元素的宽度,然后根据宽度定义弹幕节点的初始位置。以父元素为body为例://css.block{position:absolute;左:0;可见性:隐藏;/*其他装饰风格*/animation:barrage5slinear0s;}//jsletstyle=document.createElement('style');document.head.appendChild(style);letwidth=window.innerWidth;letfrom=`from{可见性:可见;-webkit-transform:translateX(${width}px);}`;letto=`to{可见性:可见;-webkit-transform:translateX(-100%);}`;style.sheet.insertRule(`@-webkit-keyframes弹幕{${from}${to}}`,0);除了耦合js计算父元素的宽度来确定弹幕节点的初始位置外,这里我们在弹幕节点中添加visibility:hidden属性,防止显示初始位置。防止弹幕节点在初始位置未确定时显示在父容器中。弹幕只有在从初始位置开始滚动时才会可见。但是这种css实现方式在实现弹幕的扩展功能时比较麻烦,比如如何控制弹幕的暂停等等。3、Canvas实现弹幕除了通过css实现弹幕的方法外,还可以通过canvas实现弹幕。通过canvas实现弹幕的原理就是时不时重绘文字,下面分步实现。获取画布letcanvas=document.getElementById('canvas');让ctx=canvas.getContext('2d');画文字ctx.font='20px微软雅黑';ctx.fillStyle='#000000';ctx.fillText('画布绘制文字',x,y);上面的fillText是实现弹幕效果的主要API,其中x代表水平方向的坐标,y代表垂直方向的坐标。只要时不时的改变x和y重绘,就可以实现动态的弹幕效果。清空绘图内容ctx.clearRect(0,0,width,height);具体实现是用定时器定时改变x,y,每次改变前清屏,然后根据改变的x,y重新绘制。当有多个弹幕时,定义:letcolorArr=_this.getColor(color);弹幕数组对应的颜色数组letnumArrL=_this.getLeft();弹幕数组对应的横坐标位置数组letnumArrT=_this.getTop();弹幕数组对应的y坐标位置数组letspeedArr=_this.getSpeed();弹幕数组对应的弹幕移动速度数组定时重绘弹幕函数为:_this.timer=setInterval(function(){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.save();for(letj=0;j