我遇到的问题是我试图为元素设置动画。我有一个递归函数animate,包含setTimeout来延迟动画。问题是调用递归方法之后的下一行在调用动画之前运行。例如,使用此代码:
this.slideTo = function(x,y) {
var originalStyle = this.element.style.cssText;
var endX = x;
var endY = y;
var pos = this.getPosition();
var startX = pos.x;
var startY = pos.y;
var distX = x - pos.x;
var distY = y - pos.y;
var totalDistance = Math.sqrt((distX*distX) + (distY*distY));
var count = 0;
var done = false;
animate(this.element);
function animate(element) {
count += 5;
var curPos = _(element).getPosition();
var curDistX = endX - curPos.x;
var curDistY = endY - curPos.y;
var curDistance = Math.sqrt((curDistX*curDistX) + (curDistY*curDistY));
var percentDone = count/totalDistance;
var moveToX = Math.round((percentDone*distX) + startX);
var moveToY = Math.round((percentDone*distY) + startY);
_(element).moveTo(moveToX,moveToY);
if(percentDone <= 1) {
setTimeout(function(){animate(element);},1);
} else {
done = true;
}
}
console.log(done);
this.element.style.cssText = originalStyle;
}
控制台显示false,因为它在动画完成之前运行。我怎么解决这个问题?顺便说一句:这是在鼠标事件上调用的。这与它有什么关系吗?
答案 0 :(得分:2)
它不起作用,因为JS,特别是setTimeout
是异步的 - 也就是说,它不会阻塞(睡眠/等待/等)。您基本上是设置超时,然后继续使用其余代码。当时间结束时,JS会调用你的函数,而它没有做任何事情。
大多数情况下,您可以通过传入动画完成时调用的回调来解决此问题(而不是设置done
或同时设置{{1}},这将是直截了当的方式。)
答案 1 :(得分:0)
尝试下一个小改变的代码:
this.slideTo = function(x,y) {
var originalStyle = this.element.style.cssText;
var endX = x;
var endY = y;
var pos = this.getPosition();
var startX = pos.x;
var startY = pos.y;
var distX = x - pos.x;
var distY = y - pos.y;
var totalDistance = Math.sqrt((distX*distX) + (distY*distY));
var count = 0;
var done = false;
function restoreState(element) {
element.style.cssText = originalStyle;
/// ....
}
function animate(element) {
count += 5;
var curPos = _(element).getPosition();
var curDistX = endX - curPos.x;
var curDistY = endY - curPos.y;
var curDistance = Math.sqrt((curDistX*curDistX) + (curDistY*curDistY));
var percentDone = count/totalDistance;
var moveToX = Math.round((percentDone*distX) + startX);
var moveToY = Math.round((percentDone*distY) + startY);
_(element).moveTo(moveToX,moveToY);
if(percentDone <= 1) {
setTimeout(function(){animate(element);},1);
} else {
done = true;
restoreState(element);
}
}
animate(this.element);
}
答案 2 :(得分:0)
简而言之,setTimeout不会停止代码的执行 - 它只是在给定的超时后运行有问题的函数:
var a = 'now';
function go(){ a = 'later'; };
setTimeout(go, 50);
console.log(a); // 'now'
setTimeout(function(){ console.log(a); },51); // 'later'
您想使用回调模式:
function animate(element, callback){
// do some stuff
if(stuffDone){
callback();
}
}
animate(element, function(){console.log(whatever); });