Я не полностью проверил код, но есть ошибка, которая соответствует вашему симптому:
timers[i] = setTimeout(function() { // ERROR?
element.style.width = origwidth + (widthpps * i) + 'px'; // <== error
element.style.height = origheight + (heightpps * i) + 'px'; // <== error
}, i * steptime);
Проблема заключается в том, что функции получат оперативную ссылку до i
, а не копию его значения на этой итерации цикла. Таким образом, все они видят i
как его последнее значение.
Это легко исправить:
timers[i] = setTimeout(makeStepFunction(i), i * steptime);
// Anywhere in the surrounding function, not in the loop:
function makeStepFunction(step) {
return function() {
element.style.width = origwidth + (widthpps * step) + 'px';
element.style.height = origheight + (heightpps * step) + 'px';
};
}
Теперь функция, которую вызовет setTimeout
, использует аргумент, переданный в makeStepFunction
, а не i
.
Вы можете сделать это без именованной функции, но это очень запутанно:
timers[i] = setTimeout((function(step) {
return function() {
element.style.width = origwidth + (widthpps * step) + 'px';
element.style.height = origheight + (heightpps * step) + 'px';
};
})(i), i * steptime);
Все это связано с тем, как замыкания (функции, которые «закрывают» данные) работают в JavaScript. Они действительно мощные, но они не сложны, когда вы знаете, как они работают. FWIW, мое сообщение в блоге Закрытия не сложны может быть полезным. Когда вы знаете, как они работают, они теряют свою тайну (и становятся еще более полезными).