动态HTML创作之三(捕捉键盘) |
| 捕捉键盘可能是与用户交互中最有力的形式了。可以设置按下或释放任何的键来控制对象。 第一件事就是怎样初始化事件。这里是基本的初始化设置“onkeydown”事件: document.onkeydown=keyDown 当这个代码被加入后,浏览器就知道当键盘被按动时,keyDown()函数将调用。无论调用什么函数都没有关系,并且,在函数名后不必跟上括号。要捕捉哪个键被按下,两种浏览器有些细微的差异,现在分别介绍: 对于 Netscape Netscape 由于使用了事件指针,因此处理键盘事件显得有些“苛刻”。必须加入一段特别的代码来告诉Netscape一直检查keydown事件。如果没有这一行代码,那么当其他事件(如mousedown)发生时,会有些混乱。 document.onkeydown=keyDown if(ns4) document.captureEvents(Event.KEYDOWN) keyDown()需要跳过一个隐含变量----我们将使用“e”字母作为例子,因为在英语单词中字母“e”最常用。 function keyDown(e) 这个“e”可以是代表刚刚按下的任意一个键,如果要知道那是一个什么键,可以使用which属性:e.which 这将返回被按下的那个键的代码(而不是字母或数字)。要把代码转变为字母或数字,可以使用: String.fromCharCode(e.which) 因此,我们可以把它们放在一起,并且写一个函数来弹出一个消息框告诉我们被按下的键的键盘码和真正的键盘值: function keyDown(e) { var keycode=e.which var realkey=String.fromCharCode(e.which) alert("keycode:"+keycode+"\nrealkey:"+realkey) } document.onkeydown=keyDown document.captureEvents(Event.KEYDOWN) 可以使用 Netscape 来试验一下这段代码: <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- function keyDown(e) { var keycode=e.which var realkey=String.fromCharCode(e.which) alert("keycode:"+keycode+"\nrealkey:"+realkey) } document.onkeydown=keyDown document.captureEvents(Event.KEYDOWN) //--> </script> </HEAD> <BODY> <p>请按一个键.</p> </BODY> </HTML> 请务必注意:如果使用Internet Explorer来测试,那么会收到IE发出的错误警告框。 对于Internet Explorer 如果使用IE来获取键盘码,那么可以跳过“e”值,可以直接使用window.event.keyCode以代替e.which。至于转换成真正键盘值的代码则是一样的:String.fromCharCode(event.keyCode) 可以使用 Internet Explorer来试验: <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- function keyDown(e) { var keycode=event.keyCode var realkey=String.fromCharCode(event.keyCode) alert("keycode:"+keycode+"\nrealkey:"+realkey) } document.onkeydown=keyDown //--> </script> </HEAD> <BODY> <p>请按一个键.</p> </BODY> </HTML> 我们可以运行以上程序,并且按键盘上的键. 同样以上代码用Netscape来检测,也会出现错误警告。 将两者结合 两大浏览器之争确实给我们带来了不小的麻烦,于是不得不寻找一段适合于两者的代码。但两种浏览器使用的是不同的字符设置。这里,建议彻底忘却真正的键盘值,仅仅使用键盘码,下面这段代码将指定“nkey”为键盘码。如果使用Netscape,那么“iekey”将会是0;反之,“nkey”设定为0。 <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- ns4=(document.layers)?true:false ie4=(document.all)?true:false function keyDown(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} alert("nKey:"+nKey+" ieKey:"+ieKey) } document.onkeydown=keyDown if(ns4) document.captureEvents(Event.KEYDOWN) //--> </script> </HEAD> <BODY> <p>请按一个键。</P> </BODY> </HTML> 可以同时使用Internet Explorer和Netscape来试验这个例子,看看它们之间对比的效果: 用键盘来移动元素 上面说了那么多有关于捕捉键盘的基础知识,现在该轮到实践了,让我们用所学的东西来做一些有趣的事情。我们可以用键盘来激活前面所提到的移动函数,先检测哪个键被按下,然后调用相应的函数来使对象移动。 function init() { if(ns4) block=document.blockDiv if(ie4) block=blockDiv.style block.xpos=parseInt(block.left) document.onkeydown=keyDown if(ns4) document.captureEvents(Event.KEYDOWN) } function keyDown(e) { if(ns4) {var nKey=e.which; var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if(nKey==97||ieKey==65) {//在按下"A"键的情况下 slide() } } function slide() { block.xpos+=5 block.left=block.xpos status=block.xpos setTimeout("slide()",30) } 这个例子完整的写法如下: <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- ns4=(document.layers)?true:false ie4=(document.all)?true:false function init() { if(ns4) block=document.blockDiv if(ie4) block=blockDiv.style block.xpos=parseInt(block.left) document.onkeydown=keyDown if(ns4) document.captureEvents(Events.KEYDOWN) } function keyDown(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if(nKey==97||ieKey==65){ slide() } } function slide() { block.xpos+=5 block.left=block.xpos status=block.xpos setTimeout("slide()",30) } //--> </script> </HEAD> <BODY onLoad="init()"> <p>请按“A”键使图像滑动</p> <div id="blockDiv" style="position:absolute;left:25;top:50;width:40"> <img src="../image/block.gif"> </div> </BODY> </HTML> 可以使用Internet Explorer或者Netscape来检验这个例子,键入“A”图像就会移动。不过很快就会发现上面这个例子的致命缺点,我们将在下面的内容中讨论。 理解“Active”变量 如果亲自用浏览器运行过上面的例子会发现一个现象:一旦图像开始滑动,我们无法使它停下来,而且越是按“A”键,它跑得越快,直到选择“刷新”。我们必须想办法解决这个问题,使用一个叫做“Active”变量的技术代表当前的移动状态,也就是判断一下:“对象现在正在移动吗?”一旦掌握了这种技术,那它就会变得非常灵活方便。大多数的移动函数都是循环执行的,它们在建立的时候并没有指定结束循环的方法,这里就需要用到这个“Active”变量。 function slide() { if(myobj.active) { myobj.xpos+=5 myobj.left=myobj.xpos setTimeout("slide()",30) } } 在这种情况下,slide()函数将仅仅在myobj.active值为“true”时运行。一旦设置的myobj.active值为“false”,那么移动函数就会停止。 使用“onKeyUp”事件 “onkeyup”事件与“onkeydown”是一样的。可以像下面这样初始化事件: document.onkeydown=keyDown document.onkeyup=keyUp if(ns4) document.captureEvents(Event.KEYDOWN|Event.KEYUP) “keyUp()”函数也是同样的,但是我们需要使当时在移动的对象在键盘释放后即停止。要做到这一点,我们可以设置的激活变量为0: function keyUp(e) { if(ns4) var nKey=e.which if(ie4) var ieKey=window.event.keyCode if(nKey==97||ieKey==65) block.active=false } 为了使代码具有更高的可靠性,需要加上更多的检测函数。“keyDown”函数里,“&&!block.active”确认了在没有块被激活的情况下才调用函数。换句话说,如果块在移动,就不要执行slide()函数了。然后把激活值设为“真”并且让块移动。“slide()”有“if(block.active)”语句以保证它仅在激活值为真时移动块,也正因为那样,当用户释放键盘时,执行也停止了。 function init() { if(ns4) block=document.blockDiv if(ie4) block=blockDiv.style block.xpos=parseInt(block.left) block.active=false document.onkeydown=keyDown document.onkeyup=keyUp if(ns4) document.captureEvents(Event.KEYDOWN | Event.KEYUP) } function keyDown(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if((nKey==97 || ieKey==65)&&!block.active) {//如果“A”键被按下 block.active=true slide() } } function keyUp(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if(nKey==97 || ieKey==65) { block.active=false //如果“A”键被释放 } } function slide() { if(block.active) { block.xpos+=5 block.left=block.xpos status=block.xpos setTimeout("slide()",30) } } 终于我们能够使用键盘完全地控制页面对象了,可以用两种浏览器来试验下面的完整例子,当按下“A”键时,图像开始滑动,当释放“A”键时,图像就会立刻停止滑动: <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- ns4=(document.layers)?true:false ie4=(document.all)?true:false function init() { if(ns4) block=document.blockDiv if(ie4) block=blockDiv.style block.xpos=parseInt(block.left) block.active=false document.onkeydown=keyDown document.onkeyup=keyUp if(ns4) document.captureEvents(Event.KEYDOWN | Event.KEYUP) } function keyDown(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if((nKey==97 || ieKey==65)&&!block.active) {//如果“A”键按下 block.active=true slide() } } function keyUp(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if(nKey==97 || ieKey==65) { block.active=false } } function slide() { if(block.active) { block.xpos+=5 block.left=block.xpos status=block.xpos setTimeout("slide()",30) } } //--> </script> </HEAD> <BODY onLoad="init()"> <p>按下“A”键移动对象,放开“A”键停止。</p> <div id="blockDiv" style="position:absolute;left:25;top:90;width:40"> <img src="../image/block.gif"> </div> </BODY> </HTML> 可以使用的键 正如前面提到过的,Netscape和Internet Explorer的字符设置不同,它们各有优点: l Netscape可以辨别按键的大小写,而IE不能。 l 但是Internet Explorer可以检测到大多数的键像Ctrl、Shift、Alt和方向键而Netscape不能做到。 下面有个小例子,如果使用Internet Explorer,它能返回ieKey;反之则返回nKey的值: <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- ns4=(document.layers)?true:false ie4=(document.all)?true:false function keyDown(e) { if(ns4) { var nKey=e.which document.keyform.keytext.value="nKey="+nKey } if(ie4) { var ieKey=event.keyCode document.keyform.keytext.value="ieKey="+ieKey } } document.onkeydown=keyDown if(ns4) document.captureEvents(Event.KEYDOWN) //--> </script> </HEAD> <BODY> <p>这是一个小小的工具,用来返回浏览器的 nKey 值或 ieKey 值。 <br>返回值的类型是根据你所使用的浏览器类型来决定的。</p> <form name="keyform"> <input type="text" name="keytext" value="请按一个按钮" size=12> </form> </BODY> </HTML> 当使用Internet Explorer检验这段代码时,在文本框中返回的是“ieKey”值,同样Netscape返回的是“nKey”值。 基本游戏控制 这里有一个彻底利用键盘控制页面上对象的例子,这种技术与我们最终的目的:游戏控制已经相差无几了。请看源程序: <HTML> <HEAD> <TITLE>DHTML Demo</TITLE> <script language="javascript"> <!-- ns4=(document.layers)?true:false ie4=(document.all)?true:false function init() { if(ns4) block=document.blockDiv if(ie4) block=blockDiv.style block.xpos=parseInt(block.left) block.ypos=parseInt(block.top) block.activeleft=false block.activeright=false block.activeup=false block.activedown=false document.onkeydown=keyDown document.onkeyup=keyUp if (ns4) document.captureEvents(Event.KEYDOWN | Event.KEYUP) } function keyDown(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if((nKey==52 || ieKey==100) && !block.activeleft) {//4 left block.activeleft=true block.activeright=false slideleft() } if((nKey==54 || ieKey==102) && !block.activeright) {//6 right block.activeright=true block.activeleft=false slideright() } if((nKey==56 || ieKey==104) && !block.activeup) {//8 up block.activeup=true block.activedown=false slideup() } if((nKey==50 || ieKey==98) && !block.activedown) {//2 down block.activedown=true block.activeup=false slidedown() } } function keyUp(e) { if(ns4) {var nKey=e.which;var ieKey=0} if(ie4) {var ieKey=event.keyCode;var nKey=0} if(nKey==52 || ieKey==100) block.activeleft=false if(nKey==54 || ieKey==102) block.activeright=false if(nKey==56 || ieKey==104) block.activeup=false if(nKey==50 || ieKey==98) block.activedown=false } function slideleft() { if(block.activeleft) { block.xpos-=5 block.left=block.xpos status="x:"+block.xpos+"y:"+block.ypos setTimeout("slideleft()",20) } } function slideright() { if(block.activeright) { block.xpos+=5 block.left=block.xpos status="x:"+block.xpos+"y:"+block.ypos setTimeout("slideright()",20) } } function slideup() { if(block.activeup) { block.ypos-=5 block.top=block.ypos status="x:"+block.xpos+"y:"+block.ypos setTimeout("slideup()",20) } } function slidedown() { if(block.activedown) { block.ypos+=5 block.top=block.ypos status="x:"+block.xpos+"y:"+block.ypos setTimeout("slidedown()",20) } } //--> </script> </HEAD> <BODY onLoad="init()"> <p> 单击任意键控制图像 <br>2=向下,4=向左,6=向右,8=向上 </p> <div id="blockDiv" style="position:absolute;left:50;top:75;width:40"> <img src="../image/block.gif"> </div> </BODY> </HTML> 当初始化页面时,显示一个静止的图像,在页面上提示用户可以利用小键盘上的2、4、6、8代表后、左、前、右四个方向控制图像的走向。当用户按下其中任何一个键不放,图像会按照指定的方向滑动。需要注意的是,这个图像的运动速度与在“控制面板”中设定的键盘重复速率有关。并且当同时按下相邻的两个方向的键时,图像会按照圆形的轨迹运动。因为它们在水平方向和垂直方向的增量相同。 |