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>