Javascript 为什么该程序中的移动仍然与按键事件的发射相耦合?

Javascript 为什么该程序中的移动仍然与按键事件的发射相耦合?,javascript,dom,keyboard,Javascript,Dom,Keyboard,将添加一个红方块作为DOM节点,并连接到键盘上的箭头键 我自己的键盘处理逻辑试图避免与发出keydown事件相关的延迟和缓解。按下箭头键时,方块应立即全速移动 但广场的移动仍然伴随着按键事件的发生 为什么会这样 此代码的工作方式是: 一个按键对象,用于维护每个箭头键代码的按键列表及其持续时间 这些列表的长度通常为零或一,因为 每个动画帧都会重置该列表 通过依赖requestAnimationFrame我曾希望能够停止依赖keydown事件 37,38,39,40幻数是箭头键的键码 cons

将添加一个红方块作为DOM节点,并连接到键盘上的箭头键

我自己的键盘处理逻辑试图避免与发出
keydown
事件相关的延迟和缓解。按下箭头键时,方块应立即全速移动

但广场的移动仍然伴随着按键事件的发生

为什么会这样

此代码的工作方式是:

  • 一个
    按键
    对象,用于维护每个箭头键代码的按键列表及其持续时间
  • 这些列表的长度通常为零或一,因为
  • 每个动画帧都会重置该列表
  • 通过依赖
    requestAnimationFrame
    我曾希望能够停止依赖keydown事件
  • 37
    38
    39
    40
    幻数是箭头键的键码
const ROOT_NODE=document.getElementById('ROOT');
const PLAYER_NODE=document.createElement('div');
const createKeyPressStore=()=>({37:[],38:[],39:[],40:[]);
常数加=(a,b)=>a+b;
常数负=(a,b)=>a-b;
const isArrow=({keyCode})=>[37,38,39,40]。包括(keyCode);
常量平移=(轴,变换)=>([x,y],平移)=>
轴=='x'?[变换(x,平移),y]:[x,变换(y,平移)];
常数归一化=(n,正常)=>(n~(归一化(持续时间,16)/16*速度);
常量移动映射={
37:翻译('x',减号),
38:翻译('y',减号),
39:翻译('x',加上),
40:翻译('y',加上)
};
常量calcLeft=({style:{left},[x])=>+left.substr(0,left.length-2)+x;
const calcTop=({style:{top},[[uu,y])=>+top.substr(0,top.length-2)+y;
const resetKeyPress=store=>((store.keyppress=createKeyPressStore()),store);
const now=()=>~~性能。now();
常量createStore=()=>({
根节点:根节点,
玩家:{node:player_node,速度:10},
按键:createKeyPressStore()
});
const onkeydown=({keyppress},e)=>(
isArrow(e)和&(按键[e.keyCode][0]&&!按键[e.keyCode][0]。停止&(按键[e.keyCode][0]。停止=现在()),
按键[e.keyCode].unshift({start:now()}),
假的
);
const onkeyup=({keypress},e)=>
isArrow(e)和&按键[e.keyCode][0]&&(按键[e.keyCode][0].stop=now();
常量计算转换=(存储,结果=[0,0])=>(
(结果=Object.entries(store.keypresss)。减少(
(p,[键,列表]=>
减少(
(p1,{开始,停止})=>(
(停止=停止| |开始),移动地图[键](p1,距离(停止-开始,存储.播放器.速度))
),
P
),
结果
)),
(store.keypresss=createKeyPressStore()),
结果
);
常量绘制=(存储,翻译=计算器翻译(存储),节点=存储.播放器.节点)=>(
(node.style.left=`${calcLeft(node,translation)}px`),
(node.style.top=`${calcTop(node,translation)}px`),
重置按键(存储)
);
const listenForEvents=store=>(
((window.document.onkeydown=e=>onkeydown(store,e)),(window.document.onkeydup=e=>onkeydown(store,e)),store
);
const initDOM=store=>(
store.player.node.setAttribute('id','player'),store.rootNode.appendChild(store.player.node),store
);
const go=store=>(draw(store),requestAnimationFrame(()=>go(store));
go(listenForEvents(initDOM(createStore()))
#根{
盒影:0.10px rgba(0,0,0,1)插入;
宽度:100%;
身高:100%;
位置:绝对位置;
保证金:0;
}
#玩家{
背景:红色;
宽度:50px;
高度:50px;
位置:绝对位置;
}

JS-Bin

我想我知道答案了。问题是,在进行中的按压会被此代码有效地取消每个动画帧

下面的代码解决了这个问题

const ROOT_NODE=document.getElementById('ROOT');
const PLAYER_NODE=document.createElement('div');
const createKeyPressStore=()=>({37:[],38:[],39:[],40:[]);
常数加=(a,b)=>a+b;
常数负=(a,b)=>a-b;
const isArrow=({keyCode})=>[37,38,39,40]。包括(keyCode);
常量平移=(轴,变换)=>([x,y],平移)=>
轴=='x'?[变换(x,平移),y]:[x,变换(y,平移)];
常数归一化=(n,正常)=>(n~(归一化(持续时间,16)/16*速度);
常量移动映射={
37:翻译('x',减号),
38:翻译('y',减号),
39:翻译('x',加上),
40:翻译('y',加上)
};
常量calcLeft=({style:{left},[x])=>+left.substr(0,left.length-2)+x;
const calcTop=({style:{top},[[uu,y])=>+top.substr(0,top.length-2)+y;
const resetKeyPress=store=>((store.keyppress=createKeyPressStore()),store);
const now=()=>~~性能。now();
常量createStore=()=>({
根节点:根节点,
玩家:{node:player_node,速度:2},
按键:createKeyPressStore()
});
const onkeydown=({keyppress},e)=>(
isArrow(e)和&(按键[e.keyCode][0]&&!按键[e.keyCode][0]。停止&(按键[e.keyCode][0]。停止=现在()),
按键[e.keyCode].unshift({start:now()}),
假的
);
const onkeyup=({keypress},e)=>
isArrow(e)和&按键[e.keyCode][0]&&(按键[e.keyCode][0].stop=now();
常量calcTranslation=(存储,结果=[0,0],inProgress=createKeyPressStore())=>(
(结果=Object.entries(store.keypresss)。减少(
(p,[键,列表]=>
减少(
(p1,{开始,停止})=>(
!stop&&start&&inProgress[key].unshift({start:now()}),
移动地图[键](p1,距离((停止| |开始)-开始,存储。播放器。速度))
),
P
),
结果
)),
(store.Keypress=inProgress),
结果