I'm trying to animate the movement of image across the canvas using requestAnimationFrame in 2 directions using a recursive function.
Animate 1 move the image in one direction on 1 click and then the opposite direction on 2nd click. Animate 2 moves the image in one direction.
Before I get to test my recursive function, my requestAnimationFrame returns an error on my first click of Animate 1. I ran a simple debug to find out that after my first click on Animate 1, the image animates successfully to the left. But as it exits the animation2(), it returns back to requestAnimationFrame to return the following error:
Uncaught TypeError: Failed to execute 'requestAnimationFrame' on 'Window': The callback provided as parameter 1 is not a function.
What causes this error? And I'm pretty sure my recursive function will not work as it is. What correction should I make?
The following is my crude coding.
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>
requestAnimationFrame(animation2(coordinate))... that's the issue, that's not a function you are passing to it, that's the result of calling that function immediately that you are passing ... tryrequestAnimationFrame(() => animation2(coordinate))insteadpausinghas to do with bad code?requestAnimationFrame(() => animation2(coordinate))?requestAnimationFrame(function { animation2(coordinate);})- i.e, now you're passing a function to RAF, as it expectsrequestAnimationFrame(animation2)so I thought I would also work if I pass a variable intoanimation2()'. Without thecoordinate` variable, I can't get the rAF to work