document.onkeydown=function(event){ console.log(event); }
1、为什么按下一个键盘按键,这个事件会一直被触发。这不符合常理。浏览器为什么要这么做?
2、我知道可以用一个状态变量来实现过滤重复触发。但是,除了onkeydown + onkeyup + var is_down + setInterval,是否有更优雅的方式来实现监听某键按下中的状态?要实现的效果是按下方向键,元素开始移动,松开方向键,元素停止移动
onkeydown
onkeyup
var is_down
setInterval
欢迎选择我的课程,让我们一起见证您的进步~~
我来回个几句,看能不能给点灵感。
第1个问题是为什么这个onkeydown是长按住会一直触发。
这是W3C标准的规范,原始设计就是这样。keydown本身是用来获取所有的键盘事件,包含ctrl、alt等等都有,不只包含一般的输入键(像123abc)之外,所有在键盘上的键都有对应值,也就是它的回传值是有个代码。会这样作的原因当然是在输入时有可能会有复合键的情况,例如ctrl+s这样的键盘输入。
最常被问到的是keydown与keypress的差异,onkeypress的设计较为不同,它是用来作键盘上的输入用的,只有一般的文字键可以使用,例如上下左右键它就没反应。虽然它keydown一样会获取得到ascii的keycode码,但keydown获取到的是英文大小写无异,而keypress获取到的是英文大小写有差异的,例如下面的例子:
keydown() a = 65, A = 65 (大小写无异) keypresss() a= 97, A = 65 (大小写有异)
另一个明显的差异在于长按,也就一直按住某个键,基本上keydown的长按就会像你说的一直触发,以文字框来说就是不断输入,而keypress并不会。但也有特例,也就是Enter这个键,以及在一个文字框中长按空白键,也会让keypress一直触发,细部再研究了。keypress不适合于使用,因为它无法获取到上下左右键。所以仍然要使用keydown,而且是要考虑到长按的情况。
第2个问题是要用方向键来长按住作移动。
这大概是作互动最基本的问题,我想你应该已有试过onkeydown + onkeyup + var is_down + setInterval的方式,你说的方式是最普遍的解决方式,也可能有使用jQuery的animate函式库,来让动画更顺畅。网上有很多范例。
并没有其他更优雅的方式来作这件事,而是在浏览器上只能用keydown+keyup来监听长按的事件,这固定的套路。更多的解决方式只是在让如何动作动得更顺畅而已。
楼上的范例就是很好的一个例子。
短按时按一下就是一下。你提到他会一直触发,可能是你长按键盘,或者键盘坏了。
2、我知道可以用一个状态变量来实现过滤重复触发。但是,除了 onkeydown + onkeyup + var is_down + setInterval ,是否有更优雅的方式来实现监听某键按下中的状态?要实现的效果是按下方向键,元素开始移动,松开方向键,元素停止移动
如果只能使用 onkeydown ,难度有点大,试着写了下面的代码,有个小缺陷。长按时,每隔0.5秒 触发一次。如果0.5秒内,连按两次,也只能执行一次。
<p id="test"></p> <style> #test{ position:absolute; left:400px; top:400px; width:0; height:0; border:solid 20px #C00; border-top-color:#090; border-bottom-color:#090; border-radius:50%; } </style> <script> var controlTest = function(event){ var me = arguments.callee; me.dom = me.dom || (function(){ var dom = document.getElementById("test"); console.log("获取DOM元素", dom); // 看下是否调用缓存 return { "37": ['←',-10,0], "38": ['↑',0,-10], "39": ['→',10,0], "40": ['↓',0,10], move: function(code){ this.lastCode = this.lastCode || 0; this.lastTime = this.lastTime || 0; if( this.lastCode === code ){ //如果每按一次,只移动一次,在这里直接return就行了 if( (new Date()).getTime() - this.lastTime < 500 ){ console.log("长按,0.5秒后才可以移动一次"); return; } } this.position = this.position || (function(){ console.log("获取DOM元素位置", dom.offsetLeft, dom.offsetTop); // 看下是否调用缓存 return [dom.offsetLeft || 0, dom.offsetTop || 0]; })(); if( code in this){ dom.style.left = this.position[0] += this[code][1]; dom.style.top = this.position[1] += this[code][2]; console.log({ direction : this[code][0], position : this.position }); }; this.lastCode = code; this.lastTime = (new Date()).getTime(); } }; })(); me.dom.move(event.keyCode); }; document.onkeydown = controlTest; </script>
如果 你是要实现无论长按多久,都只执行一次。能允许 使用 onkeyup + onkeydown 实现,就完美了。
<p id="test"></p> <style> #test{ position:absolute; left:400px; top:400px; width:0; height:0; border:solid 20px #C00; border-top-color:#090; border-bottom-color:#090; border-radius:50%; } </style> <script> var controlTest = function(event){ var me = arguments.callee; me.dom = me.dom || (function(){ var dom = document.getElementById("test"); console.log("获取DOM元素", dom); // 看下是否调用缓存 return { "37": ['←',-10,0], "38": ['↑',0,-10], "39": ['→',10,0], "40": ['↓',0,10], move: function(code, eventType){ if( eventType != "keydown" ){ this.lastCode = undefined; return; } if( !! this.lastCode ){ return; } this.position = this.position || (function(){ console.log("获取DOM元素位置", dom.offsetLeft, dom.offsetTop); // 看下是否调用缓存 return [dom.offsetLeft || 0, dom.offsetTop || 0]; })(); if( code in this){ dom.style.left = this.position[0] += this[code][1]; dom.style.top = this.position[1] += this[code][2]; console.log({ direction : this[code][0], position : this.position }); }; this.lastCode = code; } }; })(); me.dom.move(event.keyCode, event.type); }; document.onkeydown = controlTest; document.onkeyup = controlTest; </script>
如果感觉代码太长,不考虑程序的可读性和性能,16行代码就够了:
<p id="test"></p> <style> #test{ position:absolute; left:400px; top:400px; width:0; height:0; border:solid 20px #C00; border-top-color:#090; border-bottom-color:#090; border-radius:50%; } </style> <script> var controlTest = function(event){ if( event.type != "keydown" ){ arguments.callee.lastKey = undefined; }; if( !!arguments.callee.lastKey ){ return; }; if( event.keyCode == "37" || event.keyCode == "39" ){ document.getElementById("test").style.left = (document.getElementById("test").offsetLeft || 0) + (event.keyCode == "37" ? -10 : 10); }else if( event.keyCode == "38" || event.keyCode == "40" ){ document.getElementById("test").style.top = (document.getElementById("test").offsetTop || 0) + (event.keyCode == "38" ? -10 : 10); } arguments.callee.lastKey = event.keyCode; }; document.onkeydown = controlTest; document.onkeyup = controlTest; </script>
按一下触发一次,这是正常的啊
我来回个几句,看能不能给点灵感。
第1个问题是为什么这个onkeydown是长按住会一直触发。
这是W3C标准的规范,原始设计就是这样。keydown本身是用来获取所有的键盘事件,包含ctrl、alt等等都有,不只包含一般的输入键(像123abc)之外,所有在键盘上的键都有对应值,也就是它的回传值是有个代码。会这样作的原因当然是在输入时有可能会有复合键的情况,例如ctrl+s这样的键盘输入。
最常被问到的是keydown与keypress的差异,onkeypress的设计较为不同,它是用来作键盘上的输入用的,只有一般的文字键可以使用,例如上下左右键它就没反应。虽然它keydown一样会获取得到ascii的keycode码,但keydown获取到的是英文大小写无异,而keypress获取到的是英文大小写有差异的,例如下面的例子:
另一个明显的差异在于长按,也就一直按住某个键,基本上keydown的长按就会像你说的一直触发,以文字框来说就是不断输入,而keypress并不会。但也有特例,也就是Enter这个键,以及在一个文字框中长按空白键,也会让keypress一直触发,细部再研究了。keypress不适合于使用,因为它无法获取到上下左右键。所以仍然要使用keydown,而且是要考虑到长按的情况。
第2个问题是要用方向键来长按住作移动。
这大概是作互动最基本的问题,我想你应该已有试过onkeydown + onkeyup + var is_down + setInterval的方式,你说的方式是最普遍的解决方式,也可能有使用jQuery的animate函式库,来让动画更顺畅。网上有很多范例。
并没有其他更优雅的方式来作这件事,而是在浏览器上只能用keydown+keyup来监听长按的事件,这固定的套路。更多的解决方式只是在让如何动作动得更顺畅而已。
楼上的范例就是很好的一个例子。
短按时按一下就是一下。
你提到他会一直触发,可能是你长按键盘,或者键盘坏了。
如果只能使用 onkeydown ,难度有点大,试着写了下面的代码,有个小缺陷。长按时,每隔0.5秒 触发一次。如果0.5秒内,连按两次,也只能执行一次。
如果 你是要实现无论长按多久,都只执行一次。
能允许 使用 onkeyup + onkeydown 实现,就完美了。
如果感觉代码太长,不考虑程序的可读性和性能,16行代码就够了:
按一下触发一次,这是正常的啊