主题:  DHTML 系列教程8 - 按键事件

QQlan

职务:版主
等级:1
金币:1.0
发贴:158
注册:2000/9/19 10:35:21
#12001/3/13 2:16:58
按键事件
翻译:QQlan

比较强大的交互式类型是通过键盘的按键来控制. 你能利用几乎所有的键的压下和释放效果. 记住, Netscape的UNIX版本Communicator 4.0 控制键盘的能力. 如果你要制作基于键击的javascript效果, 那么, 它在UNIX和Linux操作系统下会无效.

首先必须理解初试化. 这里是一个简单的初始化"onKeydown"事件.

document.onkeydown = keyDown

当代码被borswer读取并且有一个键盘的键被按下, 就调用 KeyDown() function.
两个brorswer对于处理被按下的键有所不同. 我们先单独举例.

Netscape
响应该事件, Netscape比IE要复杂一些. 你不得不多写一行不断的检查是否有键被按下. 如果不增加这一行, 它将和其他的事件, 比如mousedown混淆起来.


document.onkeydown = keyDown
if (ns4) document.captureEvents(Event.KEYDOWN)


keyDown必须递交一个隐藏变量 -- 我使用字母"e" ,因为这是一般多数的表示方法.

function keyDown(e)

这个"e"表示被安下的键. 你可以使用 which 属性找到被按下的是哪个键.
e.which
这行将获得该键的指针编码 -- 不是被按下的字母或者数字. 转换编码成为数字, 你还需要使用:
String.fromCharCode(e.which)
现在把它们放在一起. 我们写一个function, 弹出一个message, 显示被按下的键的keycode和真正的键符.

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)

查看范例 www.dansteinman.com/dynduo/examples/keystrokes-n.html (Netscape only)

Internet Explorer

IE写法类似但是你不用使用"e"值.

你可以用 window.event.keyCode 代替 [b] e.which

转换成真实的键值用法相同: String.fromCharCode(event.keyCode).

function keyDown() {
    var keycode = event.keyCode
    var realkey = String.fromCharCode(event.keyCode)
    alert("keycode: " + keycode + "\nrealkey: " + realkey)
}

document.onkeydown = keyDown

document.onkeydown = keyDown

查看范例: www.dansteinman.com/dynduo/examples/keystrokes-ie.html (Internet Explorer only)


合二为一

如果你同时打开两个browser, 你会发现效果几乎相同. 除了由于两个browser使用不同的字符集, 所以他们显示出不同的keycodes. 由于这个原因你不得不为两个browser分别写代码, 没有捷径可走.

我的建议是使用keycodes, 而彻底忘记真正显示的键值. 下面的一段代码中, 如果你使用NS
-- 把 nKey 赋值给keycode, 把 ieKey 赋值为0; 如果使用IE, 那么 ieKey 赋值给keycode, 把 nKey 赋值为0. 然后它显示最后的结果.


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)


查看范例: www.dansteinman.com/dynduo/examples/keystrokes-both.html

现在好东东来也....

通过按键移动

现在你可以使用键盘激活移动functions. 首先检查哪个键被按下, 然后调用functions移动你的object. 下面的例子中, 我使用字母"A" 激活sliding function (滑动程序). 对于"A"键, 它的nKey是97, ieKey是65. 我所要做的就是检查这两个值, 然后调用"slide"子程序.

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) { // if "A" key is pressed
        slide()
    }
}

function slide() {
    block.xpos += 5
    block.left = block.xpos
    status = block.xpos // not needed, just for show
    setTimeout("slide()",30)
}


查看范例:http://www.dansteinman.com/dynduo/examples/keystrokes-slide1.html


理解 "Active" 变量

最后的script有些局限. 一旦移动开始, 你没有办法使它停下, 而且如果按下该键次数越多, 它就移动的越快. 现在我们才修正它.

我已经使用了"active" 变量来表示当前的移动状态. ...动么? 不动么? 一旦你习惯这样的方式, 凡事垂手可得. 因为, 多数移动functions都是递归方式, 没有停止的办法, 这就是"active" 变量出现的原因. 嵌入"if" 声明到slide function中, 你能控制这个function重复还是不重复. 通常我们会写成:

function slide() {
    if (myobj.active) {
        myobj.xpos += 5
        myojb.left = myobj.xpos
        setTimeout("slide()",30)
    }
}

上例中, 只有当myobj.active的值为 true 那么, slide() function 才运行. 反之, myobj.active为false, 移动将停止. 懂的了这些, 我们可以在script里增加更多的控制.

使用 onKeyUp 和 "Active" 变量

onKeyup function和 onKeyDown的用法几乎相同. 你可以同时初始化 keydown 和 keyup:

document.onkeydown = keyDown
document.onkeyup = keyUp
if (ns4) document.captureEvents(Event.KEYDOWN | Event.KEYUP)


keyUp() function也一样. 但是我们希望当按键被释放, 物体停止移动. 所以我们要把我们的block的active 变量设为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
}


我们还需要增加一些代码, 进行彻底"error"校验. 看一下下面的代码, 看你是不是能理解. keyDown function中, &&!block.active是:当block没被激活之前, 用来调用function的.换句话说, 如果block已经在移动, 那么就没有必要再次调用slide(). 接着我们设置active的值为true, 然后移动物体. slide() function中, 使用 if (block.active) 声明, 只有当active值为true, 才执行移动. 用这个方法, 当我们释放按下的键, 移动将被停止.


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) { // if "A" key is pressed
        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 // if "A" key is released
    }
}

function slide() {
    if (block.active) {
        block.xpos += 5
        block.left = block.xpos
        status = block.xpos // not needed, just for show
        setTimeout("slide()",30)
    }
}



查看范例:http://www.dansteinman.com/dynduo/examples/keystrokes-slide2.html

哪个键我可以使用?

正如我先前说过的, NS和IE处理字符集有所不同. 通常, 所有的字母, 数字, 符号, 空格和Enter都工作正常. 你可以查看我的 nKey and ieKey Finder 得到相关细节.


游戏控制
这里有几个游戏, 可以让你看到用我们学到的技巧可以完成这些功能.

Game Controls 1 - utilizes left/right/up/down keys to move an object in any direction
Game Controls 2 - the controls behind my Follow the Leader demo
Game Controls 3 - the controls behind my StarThruster game



-------------------------------------------------------------
5DMedia版权所有, 转载请注明出处!