我有一个带有动画条的音乐播放器,可以显示歌曲中的当前位置。它使用requestAnimationFrame
进行渲染,并将div的width
样式更改为X%,其中X是当前歌曲的时间百分比。
这导致Chrome中使用大量CPU,我相信由于每帧都会进行不断的回流工作。我可以使用哪些其他选项来消除回流并减少CPU?
另外两个要求:此网页是后端音乐服务器上的Web UI。它没有使用任何HTML5媒体元素。因此,当歌曲已经部分结束时,可以加载页面,因此位置不会始终在0到100之间设置动画。
下面的小提示显示我的机器上有大约30%的CPU,这似乎有点高动画矩形。
var pos = 0;
var s = document.getElementById('i');
f = function() {
window.requestAnimationFrame(f);
pos += .03;
s.style.width = pos + '%';
}
f();
#i {
background-color: red;
position: absolute;
}
<div id="i">
</div>
答案 0 :(得分:3)
您可以通过多种方式制作一个不会导致重新布局的纯CSS进度条,以下是一些示例:
animation
- http://jsbin.com/yoqabe/edit?html,css,js,output
我认为最有效的方法之一就是使用动画来控制线性渐变的背景位置。唯一的缺点是你只能播放/暂停动画。
background-position
- http://jsbin.com/veyibe/edit?html,css,js,output
如果您需要能够使用JS更新位置,那么我建议更新渐变的background-position
并应用CSS过渡,进行去抖动以避免更新太快。
translateX
: http://jsbin.com/zolurun/edit?html,js,output
您还可以使用CSS变换来滑动容器内的进度条,这也应该避免重新绘制。
这些链接也可能有用:
答案 1 :(得分:1)
您可以考虑使用其他不需要布局操作的CSS属性,例如background-size
。
使用CSS动画代替requestAnimationFrame
。
var bar = document.getElementById('i');
function playSong(currentTime, duration) {
bar.style.animationDuration = duration + 's';
bar.style.animationDelay = - currentTime + 's';
}
playSong(3, 10);
&#13;
#i {
height: 1em;
background-image: linear-gradient(red, red);
background-repeat: no-repeat;
animation: bar linear;
}
@keyframes bar {
from { background-size: 0% 100%; }
to { background-size: 100% 100%; }
}
&#13;
<div id="i"></div>
&#13;
答案 2 :(得分:0)
如果您在进度条上使用position: absolute
或position: fixed
,则应该可以防止页面上的大量回流。
答案 3 :(得分:0)
使用
timeupdate
,元素的currentTime属性指示的时间已更改。
试试这个:
var audio = document.getElementById("audio");
function updateProgress() {
var progress = document.getElementById("progress");
var value = 0;
if (audio.currentTime > 0) {
value = Math.ceil((100 / audio.duration) * audio.currentTime);
}
progress.style.width = value + "%";
}
audio.addEventListener("timeupdate", updateProgress, false);
&#13;
#progressBar {
border: 1px solid #aaa;
color: #fff;
width: 295px;
height: 20px;
}
#progress {
background-color: #ff0000; // red
height: 20px;
display: block;
height: 100%;
width: 0;
}
&#13;
<div id="progressBar"><span id="progress"></span>
</div>
<audio id="audio" controls>
<source src="http://www.w3schools.com/tags/horse.ogg" type="audio/ogg" />
<source src="http://www.w3schools.com/tags/horse.mp3" type="audio/mpeg" />Your browser does not support the audio element.
</audio>
&#13;
答案 4 :(得分:0)
您呈现的剧本与您想要的剧本并不相关,您在requestAnimationFrame
上制作动画,但实际上,每当“歌曲百分比”发生变化时,您都会制作动画。
假设您有一个功能(例如getSongPer()
),它返回当前播放歌曲的百分比:
var oldPos, pos = 0;
var s = document.getElementById('i');
f = function() {
oldPos = pos;
pos = getSongPer();
if(oldPos !== pos){
s.style.width = pos + '%';
}
if(pos<100){
window.requestAnimationFrame(f);
}
}
f();
我没有测试它,但我希望它更轻,性能也会受到百分比精度的影响,例如:如果您具有零位精度,则将有大约100个动画更改,对于之后的每个数字,将会有大约十倍的动画更改。
答案 5 :(得分:0)
CSS:
function getToken(params) {
return new Promise((resolve, reject) => {
request.post(params, function(err, res, body) {
resolve(JSON.parse(body).token);
})
})
}
function getDevice(token, id, callback) {
request.get(..., function(err, res, body){
callback(err, body)
})
}
function async myExecutionMethod() {
let token = await getToken(myParams) // Should be a String of my token
let device = getDevice(token, 1234, cb)
}
myExecutionMethod();
JS:
#progress-bar {
background-color: red;
height: 10px;
width: 100%;
transform-origin: 0 0;
}
将宽度设置为100%时,您将获得全宽彩色条。
然后我们可以应用比例变换来设置条形的宽度而不需要回流。
但是哦,它可以扩展到中间。我们可以通过使用'use strict'
var progressBar = document.getElementById('progress-bar')
function setProgress(percentage) {
requestAnimationFrame(function () {
progressBar.style.transform = 'scaleX(' + percentage + '%)'
})
}
setProgress(10)
将变换的原点设置到左上角来解决这个问题,x和y为0。
然后我们在requestAnimationFrame中包装样式更改,让浏览器优化何时应用更改。
的Bam!您有一个高性能的零回流进度条。