画布:按下键时出现奇怪的行为

时间:2017-04-02 23:22:55

标签: javascript canvas

默认情况下,我的画布矩形应该从左向右移动。当按下键时,它应该开始向下移动。



var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    x = 0,
    y = 0;

function draw(x_move, y_move) { 
  requestAnimationFrame(function() {
    draw(x_move, y_move);
  }); 
  ctx.beginPath();
  ctx.rect(x, y, 20, 20);
  ctx.clearRect(0, 0, canvas.width, canvas.height); 
  ctx.fillStyle = "#ffffff";
  ctx.fill();
  ctx.closePath();
  x = x + x_move;
  y = y + y_move; 
} 

draw(1, 0);

document.addEventListener('keydown', function(event) {
  //console.log(event.keyCode); 
  if (event.keyCode == 40) {
    draw(0, 1); 
  }
});

canvas { background-color: red; }

<canvas id="canvas" width="600" height="400"></canvas>
&#13;
&#13;
&#13;

使用上面的代码,您至少可以注意到两个问题:

  1. 按下键时,矩形向下移动,但也一直向右移动。
  2. 当您多次按下向下键时,速度会增加。
  3. 如何解决这些问题?

3 个答案:

答案 0 :(得分:2)

查看你打电话的地方

requestAnimationFrame(function() {
    draw(x_move, y_move);
  });

您现在递归调用draw()

现在,每次拨打draw()时,都会一遍又一遍地调用它。当你从keydown事件中调用它时,你会经常调用它2倍,然后在第二次按它时经常调用3倍等等。

我并不完全清楚你的目标是什么,但是如果你想通过按下来调整方块的轨迹,你可以这样做:

document.addEventListener('keydown', function(event) {
  //console.log(event.keyCode); 
  if (event.keyCode == 40) {
    adjustDownwardTrajectory();
  }
});

并让adjustDownwardTrajectory()改变一些向下的轨道变量,以便:

function draw(x_move, y_move) { 
  requestAnimationFrame(function() {
    draw(x_move, y_move);
  }); 
  ctx.beginPath();
  ctx.rect(x, y, 20, 20);
  ctx.clearRect(0, 0, canvas.width, canvas.height); 
  ctx.fillStyle = "#ffffff";
  ctx.fill();
  ctx.closePath();
  x = x + x_move;
  y = y + y_move + downwardTrajectory;
} 

答案 1 :(得分:1)

我相信这就是你想做的事情(而且你很亲密!)。我希望这是你正在寻找的行为。

相关要点:将Nonex_move包装在具有这些功能的闭包中可能是一个好主意,这样您就可以避免在其他部分中意外更改它们。该程序。这样,您实现的用于更改方形方向的函数将具有对这些变量的私有访问权限。

&#13;
&#13;
y_move
&#13;
var canvas = document.getElementById('canvas'),
  ctx = canvas.getContext('2d'),
  x = 0,
  y = 0;

var x_move = 1;
var y_move = 0;

function draw() {
  requestAnimationFrame(function() {
    draw();
  });

  ctx.beginPath();
  ctx.rect(x, y, 20, 20);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "#ffffff";
  ctx.fill();
  ctx.closePath();
  x = x + x_move;
  y = y + y_move;
}

draw();

document.addEventListener('keydown', function(event) {
  //console.log(event.keyCode); 
  if (event.keyCode == 40) {
    x_move = 0;
    y_move = 1;
  }
});
&#13;
canvas {
  background-color: red;
}
&#13;
&#13;
&#13;

答案 2 :(得分:0)

keyboardEvent.keyCode是折旧财产。您应该使用keyboardEvent.codekeyboardEvent.key他们提供的命名密钥比管理密钥代码更容易管理。

您可以使用fillRect而不是rect,并且不需要使用beginPathfill。您不需要使用closePath只有在想要关闭形状时使用它(即从最后一个点到第一个点添加一条线)rect已经关闭

您可以直接将回调设置为requestAnimationFrame

的参数

将相关数据分组在一起是值得的。在这种情况下,正方形有一个位置xy和一个在对象中更好的增量位置(x_movey_move)。您有相关数据的好线索是当您发现自己为一组变量添加相同的名称时。对象还可以包括drawupdate

等函数形式的行为
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// list of named keys to record state of
const keys = {
   ArrowDown: false,
};
// create key event listeners
document.addEventListener('keydown', keyEvent);
document.addEventListener('keyup', keyEvent);

// define the square
const square = {
    x : 0,  // position
    y : 0,
    dx : 0, // delta pos
    dy : 0,
    draw () {  // function to render the square
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(this.x, this.y, 20, 20);
    },
    update () { // function to update square
        if(keys.ArrowDown){
            this.dx = 0;
            this.dy = 1;
        }else {
            this.dx = 1;
            this.dy = 0;
        }
        this.x += this.dx;
        this.y += this.dy;
    }
}

// main animation update function called once per frame 1/60th second
function update () {
  requestAnimationFrame(update);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  square.update();
  square.draw();
}

// key event records named key state (false up, true down)
function keyEvent (event) {
   if(keys[event.code] !== undefined){
      keys[event.code] = event.type === "keydown";
   }
}