如何使Vanilla Javascript动画不那么滞后
How to make Vanilla Javascript animation less laggy?
我有一段代码,应该用来移动这个图像(id="background"),我已经在本地下载了它,它非常大。当我将鼠标悬停在某个div的顶部时,它应该会移动。然后,这会更改不透明度CSS值,js会检测到该值,从而使图像移动。js代码如下:
setInterval(function(){
var element = document.getElementById('background'),
style = window.getComputedStyle(element),
left = style.getPropertyValue('left');
left = left.replace(/px/g, "")
left = parseInt(left,10)
if(getOpacity('rightbar') == .5){
document.getElementById('background').style.left = left - 8 + 'px'
}
if(getOpacity('leftbar') == .5){
document.getElementById('background').style.left = left + 8 + 'px'
}
},10)
getOpacity(idName)
函数如下所示:
function getOpacity(param){
var element = document.getElementById(param),
style = window.getComputedStyle(element),
opacity = style.getPropertyValue('opacity');
return opacity
}
所以问题是,无论我使用什么运动值或setInteveral
时间,动画总是显得滞后。有没有一种方法可以用vanilla-js让它变得平滑,或者更好的方法是,取消不透明度检测,用CSS来完成这一切?
当我把上面的代码放在小提琴里时,它运行得很好,但当它真正运行全浏览器(在我的个人chrome窗口上)时,它看起来是这样的。
注意:我在4k显示器上运行这个完整的浏览器窗口,这对chrome来说太难处理了吗?
1。使用requestAnimationFrame
而不是setInterval
这表示浏览器希望在下一次重绘之前执行某些操作。您提供的回调每帧执行一次。
(如果这很重要:requestAnimationFrame
在IE9及以下版本中不起作用。)
2.在值之间,每帧不要增加固定值
当使用requestAnimationFrame
和使用setInterval
时,帧之间的时间差都不同。
您可以在开发者工具栏中使用类似的东西来验证这一点:
var last = new Date();
function onFrame(){
var now = new Date();
console.log(new Date() - last);
last = now;
requestAnimationFrame(onFrame);
}
onFrame();
开发者控制台将以毫秒为单位输出帧时间,如下所示:
16
17
17
15
19
...
如果在蒸发间隔上以固定的量增加位置(在不透明度等方面不太明显),动画将看起来锯齿状。因此,不执行left = left + 8;
,而是根据当前时间计算您在动画中的位置,类似于以下内容:
var myElement = ...;
var initialOpacity = 1.0;
var targetOpacity = 0.5;
var duration = 2000;
var startTime = new Date();
function animation() {
var delta = Math.min(1, (new Date() - startTime) / duration);
// delta is now a number in the range [0 ... 1]
myElement.style.opacity = initialOpacity + delta * (targetOpacity - initialOpacity);
if (delta < 1) requestAnimationFrame(animation);
}
requestAnimationFrame(animation);
是的,这个例子是不透明的,而不是位置,但你明白了——你的老师不能声称你是复制粘贴的;——)
3.不要在JS和CSS之间来回读写
假设图像的初始位置与视口无关(例如left: -10%
),则无需读取每帧上的位置。当您的JavaScript是唯一更改left
属性的东西时,为什么要从CSS中读取它?将其保存在一个变量中,并从JavaScript中将其设置为CSS。
var initialX = ComputeCssXPosition(myElement);
...
function animate() {
...
myElement.style.left = computedNewXPosition;
}
如果您想在用户悬停元素时更改位置,请在JS中使用鼠标事件。
myElement.addEventListener('mouseover', function (ev) { ... });
myElement.addEventListener('mouseout', function (ev) { ... });
备选方案:使用CSS转换
Shomz已经在回答中提到了。
最好的方法是使用requestAnimationFrame
而不是setInterval
,并且不检查样式更改,而是使用鼠标悬停侦听器(太多通信:CSS->JS->CSS->JS…)。请参阅此处:https://jsfiddle.net/yqpun3eb/4/
但是,如果您仍然想使用setInterval
,您可以简单地将转换CSS规则放在background
元素上。例如:
#background {transition: left 0.2s linear}
这将平滑所有的值变化,因为CSS的性能要好得多,所以即使在4K屏幕上也应该很好。问题是您的更改可以跳跃8个像素。
在我的机器上使用0.2秒似乎效果不错:https://jsfiddle.net/yqpun3eb/3/
哦,顺便说一句,你想要好的性能,但你为什么用这个来强奸系统:
function getOpacity(param){
var element = document.getElementById(param),
style = window.getComputedStyle(element),
opacity = style.getPropertyValue('opacity');
return opacity
}
这不会创建额外的变量(无论如何你都不需要):
function getOpacity(param){
return window.getComputedStyle(document.getElementById(param))
.getPropertyValue('opacity');
}
最后,这里有一个使用requestAnimationFrame
的稍微优化的版本(我就是这样做的+使用监听器而不是读取样式值):https://jsfiddle.net/yqpun3eb/4/
- 如何设置html元素填充的动画
- 如何使用动画实现纸张推车
- Javascript:为什么我的Raphaeljs动画滞后?它'It’s甚至不一致
- 选择2.js和jQuery幻灯片动画滞后/抖动
- 始终运行的 Web 应用程序上的动画滞后和性能问题
- Javascript:悬停时滞后;制作幻灯片动画
- Javascript:带有参数的函数会导致动画滞后
- 淡入淡出背景颜色更改动画会滞后并减慢速度
- "滞后“;魔兽世界动画网站
- HTML动画,无滞后
- 如何使Vanilla Javascript动画不那么滞后
- scrollTop动画在chrome中是滞后的,但在firefox中工作得很好(背景尺寸:封面问题?)
- HTML5/JavaScript游戏在制作动画时的严重滞后
- SVG动画在调整大小后非常滞后(专家)
- JavaScript动画在几个循环后滞后
- jQuery动画意外滞后
- 画布外 - 左侧导航栏动画在关闭时非常跳跃/滞后
- 为什么我的jQuery SlideDown动画滞后/跳跃
- 动画图像数组滞后
- 动画:jQuery VS CSS:jQuery滞后,为什么?-jsFiddle比较/示例