人体animation不平滑

下面代码中的“spaceShip”在按住任何一个箭头键的开始时并不平滑。 它移动一步,冻结一秒钟,然后“顺利”移动。 我怎样才能使它从一开始就顺利地移动,而不是“冻结”?

我的代码:

<!doctype html> <html> <head> <meta http-content="Content-type" charset="utf-8"> <title>Make body move smoothly</title> <style type="text/css"> body { } canvas { margin: auto; position: absolute; left: 0; top: 0; right: 0; bottom: 0; border: 1px solid black; } </style> </head> <body> <canvas id="canvas" width="400" height="600"></canvas> <script type="text/javascript"> // Set up requestAnimationFrame and cancelAnimationFrame (function() { var lastTime =0; var vendors=['ms', 'moz', 'webkit', 'o']; for(var x=0; x<vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame=window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+ 'CancelAnimationFrame'] || window[vendors[x] +'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame=function(callback, element) { var currTime =new Date().getTime(); var timeToCall =Math.max(0, 16 - (currTime - lastTime)); var id =window.setTimeout(function() { callback(currTime+timeToCall); }, timeToCall); lastTime =currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame=function(id) { clearTimeout(id); }; }()); var canvas; var ctx; // ship data var shipPositionX = document.getElementById('canvas').width/2; var shipPositionY = document.getElementById('canvas').height - 30; var deltaShipPositionX = 10; var deltaShipPositionY = 10; function init() { canvas = document.getElementById('canvas'); ctx = canvas.getContext('2d'); draw(); } function draw(){ clear(); createRectangleToCoverCanvas(); createSpaceShip(shipPositionX, shipPositionY, 10); requestAnimationFrame(draw); } function clear(){ ctx.clearRect(0, 0, document.getElementById('canvas').width, document.getElementById('canvas').height); } function createRectangleToCoverCanvas(){ ctx.fillStyle = 'black'; ctx.strokeStyle = 'black'; ctx.beginPath(); ctx.rect(0, 0, canvas.width, canvas.height); ctx.closePath(); ctx.fill(); ctx.stroke(); } function createSpaceShip(x, y, radius) { ctx.fillStyle = 'white' ctx.strokeStyle = 'white' ctx.beginPath(); ctx.rect(x, y, 20, 20); ctx.closePath(); ctx.fill(); ctx.stroke(); } function moveSpaceShip(event){ switch(event.keyCode){ // left case 37: if(shipPositionX - deltaShipPositionX + 15 > 0){ shipPositionX -= deltaShipPositionX; } break; // up case 38: if(shipPositionY - deltaShipPositionY + 15 > 0){ shipPositionY -= deltaShipPositionY; } break; // right case 39: if(shipPositionX + deltaShipPositionX < document.getElementById('canvas').width){ shipPositionX += deltaShipPositionX; } break; //down case 40: if(shipPositionY + deltaShipPositionY < document.getElementById('canvas').height){ shipPositionY += deltaShipPositionY; } break; } } window.addEventListener('load', init); window.addEventListener('keydown', moveSpaceShip, true); </script> </body> </html> 

注意我的代码和这个例子之间的区别: http : //atomicrobotdesign.com/blog_media/sprite_sheet/spritesheet.html

看看这个例子是否顺利,但是我的“太空船”不是? 为什么会发生,我该如何解决? 是因为这个例子使用了一个精灵(但这似乎没有多大意义)?

问题是你等待每个keydown事件来更新船位。
keydown事件在它再次触发之前有一个延迟:您在开始时遇到的延迟以及您在每次重绘时所面临的跳跃。

这里的解决scheme是在keydown上触发移动并在keyup上释放它。 这样,只要你按下button,你的船就会平稳地移动。

 // Im' assuming most of visitors here have recent browsers, so I removed the rAF polyfill for readibility // If you wrap it after the canvas element decalaration, you can already populate this variable, it will avoid that you make a lot of calls to document.getElementById() var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); // ship data var shipPositionX = canvas.width / 2; // Just for the snippet height var shipPositionY = 0; var deltaShipPositionX = 10; var deltaShipPositionY = 10; //Removed the init() function, since our elements are loaded. function draw() { clear(); createRectangleToCoverCanvas(); createSpaceShip(shipPositionX, shipPositionY, 10); } function clear() { ctx.clearRect(0, 0, canvas.width, canvas.height); } function createRectangleToCoverCanvas() { ctx.fillStyle = 'black'; ctx.strokeStyle = 'black'; ctx.beginPath(); ctx.rect(0, 0, canvas.width, canvas.height); ctx.fill(); ctx.stroke(); } function createSpaceShip(x, y, radius) { ctx.fillStyle = 'white' ctx.strokeStyle = 'white' ctx.beginPath(); ctx.rect(x, y, 20, 20); ctx.fill(); ctx.stroke(); } // instantiate a variable that will store our animationFrame id, so we can cancel it further var raf, // the direction object, with an x and y values direction = { x: 0, y: 0 }; // we can set a speed variable var speed = 2.5; function triggerMoveSpaceShip(event) { switch (event.keyCode) { // left case 37: // update the direction object direction.x = -speed; // avoid the scroll in the snippet event.preventDefault(); break; // up case 38: direction.y = -speed; event.preventDefault(); break; // right case 39: direction.x = speed; event.preventDefault(); break; //down case 40: direction.y = speed; event.preventDefault(); break; } // if we haven't initiated the animation yet, and that our direction is not 0, then do it now if (!raf && (direction.x || direction.y)) moveSpaceShip(); } function releaseMoveSpaceShip(event) {; switch (event.keyCode) { // left case 37: //reset this direction direction.x = 0; break; // up case 38: direction.y = 0; break; // right case 39: direction.x = 0; break; //down case 40: direction.y = 0; break; } if (!direction.x && !direction.y) { // if none of the directions is set, stop the animation cancelAnimationFrame(raf); raf = undefined; } } function moveSpaceShip() { // declare our animation function var move = function() { // update the positions without going out of the screen // Sorry, this is dirty... if(direction.x){ if( (shipPositionX > 0 && shipPositionX < canvas.width-20) || (shipPositionX <= 0 && direction.x > 0) || (shipPositionX >= canvas.width-20 && direction.x < 0)) shipPositionX += direction.x; } if(direction.y){ if( (shipPositionY > 0 && shipPositionY < canvas.height-20) || (shipPositionY <= 0 && direction.y > 0) || (shipPositionY >= canvas.width-20 && direction.y < 0)) shipPositionY += direction.y; } // finally draw ou ship draw(); // update our raf id raf = requestAnimationFrame(move); }; // let's go ! raf = requestAnimationFrame(move); } draw(); window.addEventListener('keydown', triggerMoveSpaceShip, true); window.addEventListener('keyup', releaseMoveSpaceShip, true); 
 canvas { margin: auto; position: absolute; left: 0; top: 0; right: 0; bottom: 0; border: 1px solid black; } body{ overflow: none; } 
 <canvas id="canvas" width="400" height="200"></canvas>