简体   繁体   English

Javascript-暂停并继续requestAnimationFrame循环

[英]Javascript - Pausing and continuing requestAnimationFrame loop

I'm trying to animate the movement of image across the canvas using requestAnimationFrame in 2 directions using a recursive function. 我正在尝试使用递归函数在2个方向上使用requestAnimationFrame在画布上动画化图像的运动。

Animate 1 move the image in one direction on 1 click and then the opposite direction on 2nd click. Animate 1单击Animate 1会在一个方向上移动图像,然后单击2则向相反的方向移动图像。 Animate 2 moves the image in one direction. Animate 2在一个方向上移动图像。

Before I get to test my recursive function, my requestAnimationFrame returns an error on my first click of Animate 1 . 在测试递归函数之前,我的requestAnimationFrame第一次单击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. 我运行了一个简单的调试程序,以发现在我第一次单击Animate 1 ,图像成功地向左动画了。 But as it exits the animation2() , it returns back to requestAnimationFrame to return the following error: 但是,当它退出animation2() ,它返回到requestAnimationFrame以返回以下错误:

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> 

Following up from the comments: 从评论中跟进:

You should read more about the requestAnimationFrame method: 您应该阅读有关requestAnimationFrame方法的更多信息:
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

The syntax is: window.requestAnimationFrame(callback); 语法为: window.requestAnimationFrame(callback);
That callback is a parameter specifying a function to call when it's time to update your animation for the next repaint. callback是一个参数,用于指定在下一次重画时更新动画时要调用的函数。

Using your code as an example: 以您的代码为例:

  • animation2 is a function animation2是一个函数
  • animation2(coordinate) is NOT a function animation2(coordinate)不是函数
  • function() { animation2(coordinate) } is a function function() { animation2(coordinate) }是一个函数

Consider reading about nameless/anonymous functions 考虑阅读有关无名/匿名函数的信息



Here is your code working without errors: 这是您的代码正常运行:

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM