初版
用css3来实现弹幕确实比较简单,只需要设置动画让弹幕从屏幕右侧移动到屏幕左侧即可,一开始是这样实现的
.danmu {
position: fixed;
left: 100%;
animation: danmu 5s linear 0s 1;
}
@keyframes danmu {
from {
left: 100%;
transform: translateX(0);
}
to {
left: 0;
transform: translateX(-100%);
}
}
在pc端测试挺流畅,效果不错,但是一拿到移动端上试,就发现这个动画不流畅,有卡顿,ios稍好,android的话即使是配置高的机器也是有卡顿,配置低的机器就更是明显。
缘由
一番研究,发现是因为keyframes中使用left,这样的话left的改变会在渲染的过程中导致reflow,从而造成卡顿。那么改进的思路就比较明确了,移除left,只使用translate。
新问题
但是全部使用translate又有新的问题,使用left:100%可以达到让弹幕从屏幕右侧开始出现,但是translate使用的百分比单位是相对于自身的,我们需要明确的给出屏幕宽度来translate,而屏幕宽度只有运行时用js才能获取到。这样一来,动画的keyframes看来是需要使用js来动态生成了。
解决方案
在需要展示动画前,动态生成一个style,根据当前屏幕宽度定义好keyframes。
// css
.danmu {
position: fixed;
left: 0;
visibility: hidden;
animation: danmu 5s linear 0s 1;
}
// 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 danmu { ${from} ${to} }`, 0);
注意,这里.danmu里设置了visibility为隐藏,不然弹幕会堆积显示在屏幕左侧,而keyframes里则设置visibility为显示,这样就使得弹幕只在动画过程中才能被看见。
这么做的原因是弹幕的初始位置为left: 0才能方便的设置弹幕头部从屏幕右侧出现然后从右向左移动到弹幕尾部消失在屏幕左侧为止。