[英]Canvas: Strange behavior when pressing key down
By default the rectangle of my canvas should move from left to right. 默认情况下,我的画布矩形应从左向右移动。 When pressing the key down, it should start moving down. 当按下键时,它应该开始向下移动。
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>
Using the code above, you may at least notice two issues: 使用上面的代码,您至少可以注意到两个问题:
How can I fix those issues? 我该如何解决这些问题?
See where you call 看看你打电话的地方
requestAnimationFrame(function() {
draw(x_move, y_move);
});
You're now recursively calling draw()
. 你现在递归调用draw()
。
Now every time you call draw()
, it gets called over and over and over again. 现在每次调用draw()
,都会一遍又一遍地调用它。 And when you call it from the keydown event, you call it 2x as often, then 3x as often on the second time you press it, etc. 当你从keydown事件中调用它时,你会经常调用它2倍,然后在第二次按下它时经常调用3倍,等等。
I'm not entirely clear on what your objective is here, but if you wanted to just adjust the trajectory of the square by pressing down, you could do something like this: 我不太清楚你的目标是什么,但如果你想通过按下来调整方块的轨迹,你可以这样做:
document.addEventListener('keydown', function(event) {
//console.log(event.keyCode);
if (event.keyCode == 40) {
adjustDownwardTrajectory();
}
});
and have that adjustDownwardTrajectory()
change some downwardTrajectory variable such that: 并使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;
}
I believe this is what you want to be doing (and you were close!). 我相信这就是你想做的事情(你很亲密!)。 I hope this is the behaviour you were looking for. 我希望这是你正在寻找的行为。
A related point : It may be a good idea to wrap x_move
and y_move
up in a closure with these functions so you avoid accidentally changing them in other parts of the program. 一个相关的观点 :将x_move
和y_move
在具有这些函数的闭包中可能是个好主意,这样可以避免在程序的其他部分中意外地更改它们。 That way the functions you implement for changing directions of the square will have private access to these variables. 这样,您实现的用于更改方形方向的函数将具有对这些变量的私有访问权限。
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; } });
canvas { background-color: red; }
<canvas id="canvas" width="600" height="400"></canvas>
keyboardEvent.keyCode
is a depreciated property. keyboardEvent.keyCode
是折旧属性。 You should use keyboardEvent.code
or keyboardEvent.key
they provided a named key which is much easier to manage than trying to remember key codes. 您应该使用keyboardEvent.code
或keyboardEvent.key
它们提供了一个命名键,它比试图记住键代码更容易管理。
You can use fillRect
rather than rect
and you don't need to use beginPath
and fill
. 您可以使用fillRect
而不是rect
,您不需要使用beginPath
和fill
。 You don't need to use closePath
you only use it if you want to close a shape (ie add a line from the last point to the first) rect
is already closed 您不需要使用closePath
,只有在想要关闭形状时才使用它(即从最后一个点到第一个点添加一条线) rect
已经关闭
You can set the callback directly as the argument for requestAnimationFrame
您可以直接将回调设置为requestAnimationFrame
的参数
It pays to group related data together. 将相关数据分组在一起是值得的。 In this case the square has a position x
, y
and a delta position ( x_move
, y_move
) that are better off in a object. 在这种情况下,正方形具有位置x
, y
和在对象中更好地关闭的增量位置( x_move
, y_move
)。 A good clue that you have related data is when you find yourself adding the same name to a set of variables. 您有相关数据的好线索是当您发现自己为一组变量添加相同的名称时。 Objects can also include behaviour in the form of functions like draw
and update
对象还可以包括draw
和update
等功能形式的行为
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";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.