传递参数以设置回调函数的动画

Pass parameter to animate callback function

本文关键字:函数 动画 回调 设置 参数      更新时间:2024-01-16

我有下面的jQuery片段,我试图将一个参数传递给animate方法的函数,但无法正确执行。

function move() {
    var points = [13, 8, 5];
    for(var pointIdx=0; pointIdx < points.length-1; pointIdx++) {
        ..
        ..
        // animate move.        
        $('#my_id', gameWindow.document).animate({ left: "50px" ,top:  "50px" }, 1500, 'linear', 
            function(pointIdx) {
                console.log("Animation: Iteration=" + pointIdx); // pointIdx is undefined at this point, why?
               ...
               ...
            }
        )
    }
}

如何做对?

谢谢!

pointIdx未定义,因为jQuery动画的完整回调没有任何可用参数。

http://api.jquery.com/animate/

完成
类型:Function()
动画完成后要调用的函数。

因此,当你在animate函数中包含参数pointIdx时,完成像这样的回调

function(pointIdx) {

您正在覆盖变量pointIdx。因为JavaScript使用一个词法变量环境堆栈,所以pointIdx会被推送到堆栈中,并带有从完整回调中传入的值。这个值是undefined,当您尝试在完整回调的执行上下文中读取变量pointIdx的值时,它会获得堆栈的最顶端值,即undefined。这就是为什么此处未定义pointIdx的原因。

为了将pointIdx的值存储在此回调中,您需要将其从参数中删除,还需要使用IIFE关闭它。

jsFiddle Demo

for(var pointIdx=0; pointIdx < points.length; pointIdx++) {
    ..
    ..
    // animate move.        
    //close over pointIdx
    (function(pointIdx){
    //now the execution context is inside of the anonymous function
    //and the value of pointIdx in the loop is stored in
    //variable pointIdx (same name for consistency) is at the top of that variable environment
    $('#my_id', gameWindow.document).animate({ left: "50px" ,top:  "50px" }, 1500, 'linear', 
        function() {
            console.log("Animation: Iteration=" + pointIdx); // pointIdx will now contain the iteration value from the for loop
           ...
           ...
        }
    )
    })(pointIdx);
}

问题在于时间-动画回调发生在1500毫秒之后,但for循环几乎立即完成。你需要这样重写:

var points = [13, 8, 5];
var pointIdx = 0;
function animateForPointIndex(index) {
    $('#my_id').animate({
        left: "50px",
        top: "50px"
    }, 1500, 'linear', function () {
        pointIdx++;
        if (pointIdx < points.length) {
            console.log("Animation: Iteration=" + pointIdx);
            // do what you need to here 
            animateForPointIndex(pointIdx);
        }
    });
}
animateForPointIndex(0);

只有当点索引小于点数组的长度时,才会在每次完成后递归调用animate函数。