Jump to content

Smooth animation with canvas


Drongo_III

Recommended Posts

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>
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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>
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.