Поэтому я хочу оживить рисование строки на холсте HTML 5 с помощью requestAnimationFrame.
Я сделал это
function animateWrapper(centerX, centerY, xAngle, yAngle, width, height) {
var request = requestAnimationFrame(animate);
var canvas = document.getElementById("drawing");
var context = canvas.getContext('2d');
function animate (centerX, centerY, xAngle, width, height) {
drawLine(centerX,centerY, centerX, centerY - height, context, request);
}
}
function drawLine(startX, startY, endX, endY, context, request) {
context.beginPath();
context.moveTo(startX, startY);
step += 0.05;
// if (step > 1) step = 1;
var newX = startX + (endX - startX) * step;
var newY = startY + (endY - startY) * step;
context.lineTo(newX, newY);
context.stroke();
if (Math.abs(newX) >= Math.abs(endX) && Math.abs(newY) >= Math.abs(endY)) {
cancelAnimationFrame(request);
step = 0;
}
}
$(document).ready(function(){
animateWrapper(100, 100, 40, 40, 400, 400);
});
Прямо сейчас centerY, xAngle, width, height не определены (что имеет смысл - они не передаются). Это приводит к тому, что endY становится NaN, поэтому анимация не возникает.
Я не уверен, как это исправить - как передать эти аргументы в рамке анимации запроса?
В вашем коде есть первая проблема: анимация не произойдет, поскольку вы только один раз вызываете requestAnimationFrame (rAF). Вы можете думать о rAF как setTimeout, который будет срабатывать, как только появится следующий экран времени, а не setInterval, который будет вызывать снова и снова каждый раз.
Вторая проблема - классическая проблема с закрытием/привязкой/расширением javascript.
Поэтому первым решением было бы перейти на более современный язык, такой как Google Dart (:-)).
Другим решением является, например, привязка вашей функции анимации к ее параметрам.
В javascript, если вы это сделаете:
var myBoundFunction = someFunction.bind(null, arg1, arg2, arg3);
затем позже, позвонив
myBoundFunction();
будет иметь тот же эффект, что и вызов:
someFunction(arg1, arg2, arg3);
посмотрите здесь более подробную информацию и об использовании первого аргумента:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Я мог бы дать вам подсказку о том, как изменить код, но в любом случае, я думаю, вам нужно оживить несколько строк, поэтому вы должны изменить способ его работы, чтобы сделать его более гибким.
Я настоятельно рекомендую вам перейти к объекту и определить строку как объект, имеющий (x, y,...) и метод рисования и обновления.
Что-то вроде (используя закрытие на этот раз):
var canvas = ... ; // do the DOM access only once
var context = ... ; // do the DOM accessd only once
var myObjectsToDraw = [];
function animate() {
... return and stop animation if some condition is met ...
requestAnimationFrame(animate);
... clear screen ..
// draw all objects
for (var i in myObjectsToDraw) myObjectsToDraw[i].draw();
// update all objects
for (var i in myObjectsToDraw) myObjectsToDraw[i].update();
}
myObjectsToDraw.push ( ... some object ... );
animate();
((если вам интересно, вот цикл анимации, который я использую: http://jsfiddle.net/gamealchemist/KVDsc/
и моя базовая скрипка с кучей небольших утилит http://jsfiddle.net/gamealchemist/Vn2Nt/))
Это должно работать:
function animateWrapper(centerX, centerY, xAngle, yAngle, width, height) {
function animate () {
drawLine(centerX,centerY, centerX, centerY - height, context, request);
}
var request = requestAnimationFrame(animate);
var canvas = document.getElementById("drawing");
var context = canvas.getContext('2d');
}
Вам не нужно вызывать animate()
с любыми аргументами, поскольку переменные centerX
, centerY
,... и height
находятся в области видимости, когда animate()
определен (т.е. они были известны в то время, поэтому вы можете просто использовать их внутри функции).
Ответ на этот вопрос перечисляет всевозможные способы, по которым переменные становятся/становятся видимыми/пригодными для использования в JavaScript: какова область переменных в JavaScript?