我写了一个自定义动画功能。它通常工作正常,但是当我使用不同的endCallbacks快速连续调用animate();
时,有时回调非常严重,导致在错误的时间执行错误操作。
问题是函数多次实例化并执行直到达到endValue。 currentValue变化得太快,我只能看到我的html页面动画中的最后一个值。这隐藏了这种不受欢迎的行为。
第二次拨打animate();
时我需要的是结束animate();
的第一个实例并触发一个带有新值和新回调的新实例。同时我想停止setTimeout()
函数,以确保没有触发错误的回调。
window.onload = function(){
document.addEventListener('click', // some button
function (){
animate(1, 10);
}, false
);
}
function animate(startValue, endValue, callback, endCallback) {
var startValue = startValue,
currentValue = startValue,
endValue = endValue,
callback = callback,
timeout = null;
loopAnimation();
function loopAnimation(){
if (currentValue != endValue){
timeout = setTimeout(function(){
currentValue++;
// Callback executes some page manipulation code
if (typeof callback !== "undefined") callback(currentValue);
console.log(currentValue);
loopAnimation();
},500)
} else {
console.log("This callback triggers some specific changes in my page");
if (typeof endCallback !== "undefined") endCallback();
}
}
}
而不是在控制台中看到: 1,2,3, - 1,4,2,5 ...... 6,9,7,10,8,9,10
我想看到: 1,2,3, - 1,2 ...... 7,8,9,10
但是,请记住,由于我在脚本中使用animate()
的方式,我不能依赖于知道输入变量的名称或范围。这使我无法自己解决它。
答案 0 :(得分:1)
虽然这不是你要求的实现,但我想知道Underscore的油门或去抖是否能满足需求?
debounce将确保您的函数每秒调用次数不超过X次 - 每次调用时仍会执行一次,但后续调用将延迟以满足您的速率限制。因此,如果你快速连续两次调用动画,debounce可以延迟第二次执行,直到第一次执行或者你有什么。
throttle基本上会忽略速率限制期间发生的呼叫。因此,如果你在100毫秒内调用你的动画10次,你可以把它扔掉,除了第一个。 (实际上,它会执行第一个,在等待期结束时加一个)。
您不需要使用所有下划线来获取这些方法;我见过人们经常从下划线复制和粘贴去抖动和/或油门功能。如果你谷歌,你可以找到一些独立的节流或去抖实现。
节流和去抖通常用于你的情况,动画。
对于你的原始规范,实际上“结束animate()的第一个实例” - 在javascript中没有很好的可靠方法。没有真正的通用方法来“取消”已经执行的功能。如果你可以使用debounce或油门工作,我认为这将减少挫败感。
答案 1 :(得分:0)
您需要的是存储您使用的最后一个超时ID。因此,下次开始新动画时,使用此超时ID和clearTimeout
清除正在进行的动画
我发现在函数本身上存储间隔很方便。
在这里查看jsbin: http://jsbin.com/nadawezete/1/edit?js,console,output
window.onload = function(){
document.addEventListener('click', // some button
function (){
animate(1, 10);
}, false
);
};
function animate(startValue, endValue, callback, endCallback) {
var currentValue = startValue;
if (animate.timeout) clearTimeout(animate.timeout);
loopAnimation();
function loopAnimation(){
if (currentValue != endValue){
animate.timeout = setTimeout(function(){
console.log(currentValue);
currentValue++;
// Callback executes some page manipulation code
if (callback ) callback(currentValue);
loopAnimation();
},500);
} else {
console.log("This callback triggers some specific changes in my page");
if (endCallback) endCallback();
}
}
}