2015-02-18 5 views
2

У меня есть следующий фрагмент кода JQuery, и я пытаюсь передать параметр в зависимости от метода одушевленным, но не может получить это право.параметр Pass анимировать функцию обратного вызова

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? 
       ... 
       ... 
      } 
     ) 
    } 
} 

Как это сделать правильно?

Спасибо!

+0

вам не нужен параметр pointIdx в функции живого. попробуйте удалить его. Кроме того, вам не хватает цитаты в '#my_id, gameWindow.document. Это должно быть «#my_id, gameWindow.document» –

+0

Вы правы, но это должно быть: $ ('# my_id', gameWindow.document) .animate (....) – Shvalb

+0

, так как я могу передать параметр в его полный Перезвони ?? – Shvalb

ответ

3

pointIdx не определено, поскольку полный обратный вызов для анимации jQuery не имеет параметров, доступных для использования.

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

полный
Тип: Function()
Функция вызываемая после завершения анимации.

Итак, когда вы включите параметр 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); 
} 
+0

Это хорошая идея, но она не работает! потому что анимация запускается с задержкой в ​​1500 миллисекунд для циклов, заканчивающихся до того, как она даже сделает первую анимацию. поэтому в конечном счете, когда он выполняет анимацию 3 раза - значение «pointIdx» ​​равно 3 во всех итерациях вместо 1,2,3. – Shvalb

+0

Я мог бы сделать то же самое без закрывающей функции, просто называя прямо «pointIdx». – Shvalb

+0

@Shvalb - Нет, это не одно и то же, потому что функция * закрывает * по значению во время выполнения. Поэтому, когда он выполняет анимацию, он все равно будет 1,2,3.Без этого, когда вы получаете 3 все 3 раза. –

2

Проблема синхронизации - анимация обратного вызова происходит после 1500 мс, но ваш цикл завершается практически мгновенно. Вам нужно переписать так:

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); 

Функция одушевленные вызывается рекурсивно после каждого завершения, только если индекс точки меньше, чем длина массива точек.

+0

это приятное решение для этого простого случая, но мне нужен цикл «для», чтобы выполнить некоторые вычисления перед запуском анимации. – Shvalb

+0

У вас фактически есть цикл for - где мой комментарий «делает то, что вам нужно здесь», вы можете делать те же вычисления, что и pointIdx. – inorganik

+0

Большое спасибо! Я советую вам взглянуть на ответ Трэвиса Дж - это более чистое решение (рекурсии в коде - это то, что я предпочитаю избегать) и отличная техника для сохранения состояния между событиями. – Shvalb

Смежные вопросы