fun*_*err 0 javascript duration setinterval
首先我想提两件事,
一:我的代码并不完美(特别是 eval 部分) - 但我想为自己尝试一些东西,看看我是否可以复制 jQuery Animation 功能,所以请原谅我的“不好”的做法,请不要建议我使用 jQuery,我想尝试一下。
二:这段代码还没有完成,我只是想弄清楚是什么让它工作得不好。
所以动画运行了大约 12 秒,而我输入的持续时间参数是 15 秒,我做错了什么?
function animate(elem, attr, duration){
if(attr.constructor === Object){//check for object literal
var i = 0;
var cssProp = [];
var cssValue = [];
for(key in attr) {
cssProp[i] = key;
cssValue[i] = attr[key];
}
var fps = (1000 / 60);
var t = setInterval(function(){
for(var j=0;j<cssProp.length;j++){
if(document.getElementById(elem).style[cssProp[j]].length == 0){
//asign basic value in css if the object dosn't have one.
document.getElementById(elem).style[cssProp[j]]= 0;
}
var c = document.getElementById(elem).style[cssProp[j]];
//console.log(str +" | "+c+"|"+cssValue[j]);
if(c > cssValue[j]){
document.getElementById(elem).style[cssProp[j]] -= 1/((duration/fps)*(c-cssValue[j]));
}else if(c < cssValue[j]){
document.getElementById(elem).style[cssProp[j]] += 1/((duration/fps)*(c-cssValue[j]));
}else if(c == cssValue[j]){
window.clearInterval(t);
}
}
},fps);
}
}
animate('hello',{opacity:0},15000);
Run Code Online (Sandbox Code Playgroud)
html:
<p id="hello" style="opacity:1;">Hello World</p>
Run Code Online (Sandbox Code Playgroud)
注意:我猜有问题
(持续时间/fps)*(c-cssValue[j])
setInterval(fps 变量)的部分或/和间隔。
提前致谢。
我不会尝试重构并弄清楚它,因为它非常不稳定。这就是说……一些事情。
不要依赖你正在制作动画的值来让你知道动画进度
一般来说,你的方法是不合理的。你最好自己跟踪进度。此外,由于您的方法,您的数学似乎太难了,应该更简单。
可以这样想:当时间过去时,您的动画就完成了,而不是当动画值似乎表明它处于最终位置时。
不要增加,设置
浮点数学是不精确的,像这样重复加法累积也会累积浮点错误。制作一些变量来为您跟踪进度会更具可读性,您可以在计算中使用这些变量。
animatedValue += changeOnThisFrame // BAD!
animatedValue = valueOnThisFrame // GOOD!
Run Code Online (Sandbox Code Playgroud)
不要做正/负有条件的舞蹈
事实证明,10 + 10和10 - (-10)真的一样的东西。这意味着您始终可以添加值,但变化率可以是负数或正数,并且该值将在适当的方向上动画。
超时和间隔不准确
事实证明,setTimeout(fn, 50)实际上意味着安排 fn 至少在 50 毫秒后调用。在这 50 毫秒之后执行的下一个 JS 运行循环将运行该函数,因此您不能依赖它是完全准确的。
也就是说,它通常在几毫秒内。但是 60fps 大约是 16ms 的帧,并且该计时器实际上可能会在 16-22ms 的可变时间内触发。因此,当您根据帧速率进行计算时,它与实际经过的时间根本不匹配。
重构复杂的数学
在这里解构这条线会很困难。
document.getElementById(elem).style[cssProp[j]] -= 1/((duration/fps)*(c-cssValue[j]));
Run Code Online (Sandbox Code Playgroud)
为什么要更复杂地分解它,以便您可以轻松了解这里发生的事情。单独重构这一行,我可能会这样做:
var style = document.getElementById(elem).style;
var changeThisFrame = duration/fps;
var someOddCalculatedValue = c-cssValue[j];
style[cssProp[j]] -= 1 / (changeThisFrame * someOddCalculatedValue);
Run Code Online (Sandbox Code Playgroud)
这样做可以更清楚地了解数学中每个表达式的含义及其用途。因为你没有在这里做,我很难想知道为什么c-cssValue[j]在那里以及它代表什么。
简单示例
这不如您拥有的能力,但它显示了您应该采取的方法。它使用动画开始时间来创建完美的值,这取决于动画应该有多完整、从哪里开始以及将要去哪里。它不使用当前动画值来确定任何内容,并保证运行整个动画长度。
var anim = function(elem, duration) {
// save when we started for calculating progress
var startedAt = Date.now();
// set animation bounds
var startValue = 10;
var endValue = 200;
// figure out how much change we have over the whole animation
var delta = endValue - startValue;
// Animation function, to run at 60 fps.
var t = setInterval(function(){
// How far are we into the animation, on a scale of 0 to 1.
var progress = (Date.now() - startedAt) / duration;
// If we passed 1, the animation is over so clean up.
if (progress > 1) {
alert('DONE! Elapsed: ' + (Date.now() - startedAt) + 'ms');
clearInterval(t);
}
// Set the real value.
elem.style.top = startValue + (progress * delta) + "px";
}, 1000 / 60);
};
anim(document.getElementById('foo'), 5000);
?
Run Code Online (Sandbox Code Playgroud)
JSFiddle:http : //jsfiddle.net/DSRst/