我正在尝试使用requestAnimationFrame
在2个方向上使用递归函数来动画图像在画布上的移动。
Animate 1
单击1朝一个方向移动图像,然后单击2n沿相反方向移动图像。 Animate 2
在一个方向上移动图像。
在测试递归函数之前,我的requestAnimationFrame
第一次点击Animate 1
时会返回错误。我进行了一次简单的调试,发现在我第一次单击Animate 1
之后,图像成功地向左移动了动画。但是当它退出animation2()
时,它返回到requestAnimationFrame
以返回以下错误:
Uncaught TypeError: Failed to execute 'requestAnimationFrame' on 'Window': The callback provided as parameter 1 is not a function.
什么原因导致此错误?而且我很确定我的递归函数将无法正常使用。我该怎么做?
以下是我的粗略编码。
var canvas = document.getElementsByTagName("canvas")[0];
canvas.width = 286;
canvas.height = 60;
var ctx = canvas.getContext("2d");
trackTransforms(ctx);
var img = new Image();
img.src = "https://www.dropbox.com/s/bq8wk2rashbsjxw/Capture.PNG?raw=1";
window.onload = function() {
redraw();
};
var button1 = false;
var pause;
var coordinate = new Array();
coordinate[0] = {
X1: 286,
X2: 136
};
coordinate[1] = {
X1: 150,
X2: 0
};
var coordinate2 = new Array();
coordinate2[0] = {
X1: 286,
X2: 136
};
coordinate2[1] = {
X1: 150,
X2: 0
};
function animation() {
var track = coordinate.slice(); // copy the array to keep track of which items are left to process after click event
coordinate.forEach(function(item, index) {
track.splice(track.indexOf(item), 1); // remove the item from the processed array
button1 = true;
animation2(item);
button1 = false;
button.onclick = function(event) {
animation(track); // call function in the callback passing in the unprocessed items array
event.target.onclick = null; // remove the click event so it can't be fired again
}
});
}
var fps = 1; // animation speed
var slideX = 0;
function animation2(coordinate) {
if (button1) {
var cornerRight = coordinate.X1; // animation in to and fro
var cornerLeft = coordinate.X2;
} else {
var cornerRight = coordinate2[0].X1; // animation in single direction
var cornerLeft = coordinate2[0].X2; // change index number to change direction
}
var cornerCenterX = (cornerLeft + cornerRight) / 2;
var canvasCenterX = canvas.width / 2;
if (cornerCenterX > canvasCenterX) {
// to determine image to move right or left
slideX -= fps;
var distanceX = Math.abs(cornerCenterX - canvasCenterX);
var pt = ctx.transformedPoint(slideX, 0);
ctx.translate(pt.x, pt.y);
redraw();
if (button1) {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(animation2(coordinate));
} else {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(animation2);
}
} else if (cornerCenterX < canvasCenterX) {
slideX += fps;
var distanceX = Math.abs(cornerCenterX - canvasCenterX);
var pt = ctx.transformedPoint(slideX, 0);
ctx.translate(pt.x, pt.y);
redraw();
if (button1) {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(animation2(coordinate));
} else {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(animation2);
}
}
}
function redraw() {
var p1 = ctx.transformedPoint(0, 0);
var p2 = ctx.transformedPoint(canvas.width, canvas.height);
ctx.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.drawImage(img, 0, 0);
}
function reset() {
var p1 = ctx.transformedPoint(0, 0);
var p2 = ctx.transformedPoint(canvas.width, canvas.height);
ctx.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
slideX = 0;
button1 = false;
}
function trackTransforms(ctx) {
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var xform = svg.createSVGMatrix();
ctx.getTransform = function() {
return xform;
};
var savedTransforms = [];
var save = ctx.save;
ctx.save = function() {
savedTransforms.push(xform.translate(0, 0));
return save.call(ctx);
};
var restore = ctx.restore;
ctx.restore = function() {
xform = savedTransforms.pop();
return restore.call(ctx);
};
var translate = ctx.translate;
ctx.translate = function(dx, dy) {
xform = xform.translate(dx, dy);
return translate.call(ctx, dx, dy);
};
var transform = ctx.transform;
ctx.transform = function(a, b, c, d, e, f) {
var m2 = svg.createSVGMatrix();
m2.a = a;
m2.b = b;
m2.c = c;
m2.d = d;
m2.e = e;
m2.f = f;
xform = xform.multiply(m2);
return transform.call(ctx, a, b, c, d, e, f);
};
var setTransform = ctx.setTransform;
ctx.setTransform = function(a, b, c, d, e, f) {
xform.a = a;
xform.b = b;
xform.c = c;
xform.d = d;
xform.e = e;
xform.f = f;
return setTransform.call(ctx, a, b, c, d, e, f);
};
// convert the mouse coordinates (in pixels) into the global space of your SVG document
var pt = svg.createSVGPoint();
ctx.transformedPoint = function(x, y) {
pt.x = x;
pt.y = y;
return pt.matrixTransform(xform.inverse());
};
}
body {
background: #eee;
margin: 1em;
text-align: center;
}
canvas {
display: block;
margin: 1em auto;
background: #fff;
border: 1px solid #ccc;
}
<input id="button" type="button" value="Animate 1" onclick="animation();" />
<input id="button2" type="button" value="Animate 2" onclick="animation2();" />
<input id="button3" type="button" value="Reset" onclick="reset();" />
<canvas id="main"></canvas>
答案 0 :(得分:0)
评论之后,
您应该阅读有关 requestAnimationFrame 方法的更多信息:
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
语法为:window.requestAnimationFrame(callback);
callback
是一个参数,用于指定当需要为下一次重绘更新动画时要调用的函数。
以您的代码为例:
animation2
是一个函数animation2(coordinate)
不是函数function() { animation2(coordinate) }
是一个函数考虑阅读有关无名/匿名函数的信息
这是您的代码正常运行:
var canvas = document.getElementsByTagName("canvas")[0];
canvas.width = 286;
canvas.height = 60;
var ctx = canvas.getContext("2d");
trackTransforms(ctx);
var img = new Image();
img.src = "https://www.dropbox.com/s/bq8wk2rashbsjxw/Capture.PNG?raw=1";
window.onload = function() {
redraw();
};
var button1 = false;
var pause;
var coordinate = new Array();
coordinate[0] = {
X1: 286,
X2: 136
};
coordinate[1] = {
X1: 150,
X2: 0
};
var coordinate2 = new Array();
coordinate2[0] = {
X1: 286,
X2: 136
};
coordinate2[1] = {
X1: 150,
X2: 0
};
function animation() {
var track = coordinate.slice(); // copy the array to keep track of which items are left to process after click event
coordinate.forEach(function(item, index) {
track.splice(track.indexOf(item), 1); // remove the item from the processed array
button1 = true;
animation2(item);
button1 = false;
button.onclick = function(event) {
animation(track); // call function in the callback passing in the unprocessed items array
event.target.onclick = null; // remove the click event so it can't be fired again
}
});
}
var fps = 1; // animation speed
var slideX = 0;
function animation2(coordinate) {
if (button1) {
var cornerRight = coordinate.X1; // animation in to and fro
var cornerLeft = coordinate.X2;
} else {
var cornerRight = coordinate2[0].X1; // animation in single direction
var cornerLeft = coordinate2[0].X2; // change index number to change direction
}
var cornerCenterX = (cornerLeft + cornerRight) / 2;
var canvasCenterX = canvas.width / 2;
if (cornerCenterX > canvasCenterX) {
// to determine image to move right or left
slideX -= fps;
var distanceX = Math.abs(cornerCenterX - canvasCenterX);
var pt = ctx.transformedPoint(slideX, 0);
ctx.translate(pt.x, pt.y);
redraw();
if (button1) {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(function() { animation2(coordinate) });
} else {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(animation2);
}
} else if (cornerCenterX < canvasCenterX) {
slideX += fps;
var distanceX = Math.abs(cornerCenterX - canvasCenterX);
var pt = ctx.transformedPoint(slideX, 0);
ctx.translate(pt.x, pt.y);
redraw();
if (button1) {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(function() { animation2(coordinate) });
} else {
if (Math.abs(slideX) < distanceX) requestAnimationFrame(animation2);
}
}
}
function redraw() {
var p1 = ctx.transformedPoint(0, 0);
var p2 = ctx.transformedPoint(canvas.width, canvas.height);
ctx.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.restore();
ctx.drawImage(img, 0, 0);
}
function reset() {
var p1 = ctx.transformedPoint(0, 0);
var p2 = ctx.transformedPoint(canvas.width, canvas.height);
ctx.clearRect(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
slideX = 0;
button1 = false;
}
function trackTransforms(ctx) {
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var xform = svg.createSVGMatrix();
ctx.getTransform = function() {
return xform;
};
var savedTransforms = [];
var save = ctx.save;
ctx.save = function() {
savedTransforms.push(xform.translate(0, 0));
return save.call(ctx);
};
var restore = ctx.restore;
ctx.restore = function() {
xform = savedTransforms.pop();
return restore.call(ctx);
};
var translate = ctx.translate;
ctx.translate = function(dx, dy) {
xform = xform.translate(dx, dy);
return translate.call(ctx, dx, dy);
};
var transform = ctx.transform;
ctx.transform = function(a, b, c, d, e, f) {
var m2 = svg.createSVGMatrix();
m2.a = a;
m2.b = b;
m2.c = c;
m2.d = d;
m2.e = e;
m2.f = f;
xform = xform.multiply(m2);
return transform.call(ctx, a, b, c, d, e, f);
};
var setTransform = ctx.setTransform;
ctx.setTransform = function(a, b, c, d, e, f) {
xform.a = a;
xform.b = b;
xform.c = c;
xform.d = d;
xform.e = e;
xform.f = f;
return setTransform.call(ctx, a, b, c, d, e, f);
};
// convert the mouse coordinates (in pixels) into the global space of your SVG document
var pt = svg.createSVGPoint();
ctx.transformedPoint = function(x, y) {
pt.x = x;
pt.y = y;
return pt.matrixTransform(xform.inverse());
};
}
body {
background: #eee;
margin: 1em;
text-align: center;
}
canvas {
display: block;
margin: 1em auto;
background: #fff;
border: 1px solid #ccc;
}
<input id="button" type="button" value="Animate 1" onclick="animation();" />
<input id="button2" type="button" value="Animate 2" onclick="animation2();" />
<input id="button3" type="button" value="Reset" onclick="reset();" />
<canvas id="main"></canvas>