尽管没有发生事件,为啥每次循环后 var yPosition 都会增加?
Posted
技术标签:
【中文标题】尽管没有发生事件,为啥每次循环后 var yPosition 都会增加?【英文标题】:Why does var yPosition increment after each loop despite no event occurring?尽管没有发生事件,为什么每次循环后 var yPosition 都会增加? 【发布时间】:2014-01-09 00:17:25 【问题描述】:var canvas = document.getElementById('gameCanvas');
var ctx = canvas.getContext('2d');
var xPosition = 0;
var yPosition = 0;
var frameLength = 20;
function gameLoop()
gameUpdate();
setTimeout(function()gameLoop(), frameLength);
function gameUpdate()
ctx.clearRect(0, 0, 480, 640);
window.addEventListener('keydown', function(event)switch(event.keyCode)case 38: yPosition -= 1; break; case 40: yPosition += 1; break;, false);
ctx.fillRect(xPosition, yPosition, 50, 50);
$(document).ready(function ()
gameLoop();
);
我正在尝试通过箭头键在画布中移动一个矩形。 X 和 Y 位置是变量 xPosition 和 yPosition。现在严格处理 Y 方向,我有一个由“keydown”的事件监听器触发的开关功能。例如,当按下向下箭头键时,它会增加 fillRect(X, Y, originX, OriginY)
中的 Y 值。这会更改全局变量,然后在 Canvas 上绘制具有新坐标的新矩形。 GameLoop 重置,冲洗重复。这就是我认为它在理论上起作用的方式。
然而,出于某种原因,即使我什么都不做,我让脚本运行的时间越长,当我按下 UP 或 DOWN 时,方块跳得越“远”。也就是说,按下它会从画布上启动它,因为它出现了由 setTimeout 经历的循环数决定的像素。为什么会这样,我该如何解决?
【问题讨论】:
您不需要在每次循环时都添加事件监听器。在 $(document).ready 上做这件事,你会没事的。 它被称为 addEventListener 是有原因的 - 它不会删除以前添加的事件监听器!! 你不需要将gameLoop
包装成function
,只需写setTimeout(gameLoop, frameLength);
感谢所有建议——确实有助于澄清问题所在。另外,感谢您指出这一点,Olaf。
【参考方案1】:
您正在多次添加该事件。只需将此行移至全局范围:
window.addEventListener('keydown', function(event)switch(event.keyCode)case...
如果不是,key 会被检测多次并因此累积
您还可以在处理程序中输入preventDefault
:
window.addEventListener('keydown', function(event)
if (event.preventDefault) event.preventDefault();
switch(event.keyCode)case ...
【讨论】:
非常感谢!为了进一步了解出了什么问题,EventListener 中的函数是如何在没有 keydown 触发器的情况下运行的?我假设发生的是每次堆叠的 EventListeners。因此,当您按下向上或向下箭头时,您实际上已经运行了该功能,例如 50 次...? @JakeL。它将产生一堆需要将事件分发到的侦听器。由于 JS 是单线程的,因此该事件链的处理最终将消耗大部分可用时间。如果您有 50 个侦听器,并且每个侦听器以 1 递增,则每次按键的结果将是 50 递增。下次你可能有 150 个听众等等。以上是关于尽管没有发生事件,为啥每次循环后 var yPosition 都会增加?的主要内容,如果未能解决你的问题,请参考以下文章
为啥尽管观察者的状态发生变化,但应用程序重启后 Flutter BloC UI 没有更新?