Drongo_III Posted September 18, 2015 Share Posted September 18, 2015 Hi I'm testing out animation using canvas.. The code below just animates a square in response to holding down one of the arrow keys. The problem is when I hold down an arrow key there appears to be a short delay before the square starts animating. I'm guessing it's something to do with the keydown event firing rapidly but I'm not sure. So if anyone has any suggestions as to why this might be happening it would help me greatly! The desired effect is for the square to animate immediately without any delay. Thanks, Drongo <!doctype html> <html> <head> <style type="text/css"> canvas { border: 1px solid #888; } </style> <script> window.onload = function(){ //initialise canvas and context c.init(); //set event handler for keydown window.addEventListener('keydown', c.setPosition.bind(c)); } //canvas var c = { cvs : null, //canvas element ctx : null, //context pos : {y:0,x:0}, inc : 5, init : function(){ //create canvas obj and context this.cvs = document.getElementById('canvas1'); this.ctx = this.cvs.getContext('2d'); //draw initial rectangle at starting point c.ctx.fillStyle = 'black'; c.ctx.fillRect(0, 0, 60, 60); }, animate: function(){ //clear the canvas this.clearContext(); //redraw in new position this.ctx.fillStyle = 'black'; this.ctx.fillRect(this.pos.x, this.pos.y, 60, 60); }, clearContext : function(){ c.ctx.clearRect(0,0,this.cvs.width,this.cvs.height); }, setPosition : function(e){ //increment position based on key console.log(e.keyCode); switch(e.keyCode){ case 40: this.pos.y += this.inc; break; case 38: this.pos.y -= this.inc; break; case 37: this.pos.x -= this.inc; break; case 39: this.pos.x += this.inc; break; } //then animate this.animate(); } } </script> </head> <body> <canvas id="canvas1" width="500" height="500"></canvas> </body> </html> Quote Link to comment https://forums.phpfreaks.com/topic/298222-smooth-animation-with-canvas/ Share on other sites More sharing options...
scootstah Posted September 19, 2015 Share Posted September 19, 2015 The delay is part of the keyboard and operating system. Notice how if you hold down a letter in a text box, you get the same delay? That delay occurs on the keydown event as well. One way to fix this is to assume that the key is held down until a keyup event occurs. So you press a key, it fires a keydown event and repeats that action until a keyup event occurs for the same key, which then stops the event. Does that make sense? Quote Link to comment https://forums.phpfreaks.com/topic/298222-smooth-animation-with-canvas/#findComment-1521150 Share on other sites More sharing options...
Drongo_III Posted September 19, 2015 Author Share Posted September 19, 2015 The delay is part of the keyboard and operating system. Notice how if you hold down a letter in a text box, you get the same delay? That delay occurs on the keydown event as well. One way to fix this is to assume that the key is held down until a keyup event occurs. So you press a key, it fires a keydown event and repeats that action until a keyup event occurs for the same key, which then stops the event. Does that make sense? Scoot you're a genius sir! I hadn't considered this was symptomatic of the way the OS handles repeating keys. Your post got me to searching out how to overcome the delay and I found a solution along the lines of what you proposed. Essentially you have a loop monitoring a keyState object to determine whether a key is up or down and then it reacts accordingly. The solution also means multiple key presses can be used at once. The code is below if anyone experiences the same problem: <!doctype html> <html> <head> <style type="text/css"> canvas { border: 1px solid #888; } </style> <script> window.onload = function(){ //initialise canvas and context c.init(); window.addEventListener('keydown', function(e){ keyState[e.keyCode || e.which] = true; }, false); window.addEventListener('keyup', function(e){ keyState[e.keyCode || e.which] = false; }); } //holds key state var keyState = {} //canvas var c = { cvs : null, //canvas element ctx : null, //context pos : {y:0,x:0}, inc : 5, init : function(){ //create canvas obj and context this.cvs = document.getElementById('canvas1'); this.ctx = this.cvs.getContext('2d'); //draw initial rectangle at starting point c.ctx.fillStyle = 'black'; c.ctx.fillRect(0, 0, 60, 60); //start keystroke monitoring this.loopPosition(); }, animate: function(){ //clear the canvas this.clearContext(); //redraw in new position this.ctx.fillStyle = 'black'; this.ctx.fillRect(this.pos.x, this.pos.y, 60, 60); }, clearContext : function(){ c.ctx.clearRect(0,0,this.cvs.width,this.cvs.height); }, loopPosition: function(){ if(keyState[37]){ this.pos.x-=1; } if(keyState[39]){ this.pos.x+=1; } if(keyState[40]){ //down this.pos.y+=1; } if(keyState[38]){ //up this.pos.y-=1; } //then animate this.animate(); //loop the method setTimeout(this.loopPosition.bind(c),10); } } </script> </head> <body> <canvas id="canvas1" width="500" height="500"></canvas> </body> </html> Quote Link to comment https://forums.phpfreaks.com/topic/298222-smooth-animation-with-canvas/#findComment-1521164 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.