您已经说过要在页面上放一个盒子或其他东西,然后用箭头键移动它。因此可分为:
在页面上放置元素
能够访问该元素
能够设定自己的位置
捕获键盘事件
1-在页面上放置元素
您可以通过将元素设置为“绝对定位”元素来完全控制其位置,从而将其放置在页面上:将其position
样式属性设置为absolute
:
<div style="position: absolute;"></div>
或更好
<style>
#target {
position: absolute;
}
</style>
<div id="target"></div>
为了使该div实际显示,您需要为其设置一些大小,并可能提供一些可见的外观:
<style>
#target {
position: absolute;
width: 10px; /* Or whatever */
height: 10px; /* Or whatever */
border: 1px solid black;
background-color: #ddd;
}
</style>
2-能够访问元素
在上方,我们为元素指定了一个ID。这意味着我们可以使用
document.getElementById
查找它。这不是访问元素的唯一方法,但是它很简单明了:
var element;
element = document.getElementById("target");
3-能够设定位置
这是通过
left
,
top
,
right
和
bottom
属性完成的,可以通过元素实例上的
style
属性进行设置。让我们将其从页面顶部放置10个像素,从页面左侧放置50个像素:
element.style.top = "10px";
element.style.left = "50px";
请注意,样式值始终是字符串,并且必须像在样式表中一样包含单位。
4-捕获键盘事件
对于箭头键,最好的选择是
keydown
事件,因为它会触发不可打印的键(如箭头)并在按住该键时重复。在这里,我们进入了许多地方,例如
jQuery,
Prototype,
YUI,
Closure或
any of several others的良好库可以为您提供帮助,因为连接事件处理程序的最佳方法是:使用DOM2样式的处理程序,但是尽管Microsoft创建了它们,但在对其进行标准化时,其名称和参数与Microsoft的名称和参数不同,因此Microsoft花了很长时间来支持该标准。因此,您必须同时处理Microsoft的方式(
attachEvent
)和标准方式(
addEventListener
)。任何好的库都提供了一种简单,统一的方法来连接事件处理程序。
This answer具有跨浏览器的
hookEvent
函数,我们可以在此示例中使用(完整的源代码也位于此答案底部的最后一个示例中)。我们将这样使用它:
hookEvent(document, "keydown", function(event) {
// This function gets called when there's a keydown event
// If we want to prevent the event from propagating (bubbling),
// we can use `event.stopPropagation();` here. Similarly, if
// we want to prevent any default action, we can use
// `event.preventDefault();` here
});
要找出按下了哪个键,我们使用
keyCode
或
which
-任何体面的库都可以为您处理的另一个跨浏览器麻烦。所以:
hookEvent(document, "keydown", function(event) {
var key = event.which || event.keyCode;
});
如果
key
不是false,则将
event.which
设置为
event.keyCode
,如果
which
是false,则将
||
设置为
left
(通过
JavaScript's Curiously Powerful top
operator)。剩下的就是处理键并移动元素:
hookEvent(document, "keydown", function(event) {
var element, left, top;
element = document.getElementById("target");
left = parseInt(element.style.left, 10);
top = parseInt(element.style.top, 10);
switch (event.which || event.keyCode) {
case 37: // Left
left = Math.max(0, left - 10);
break;
case 39: // Right
left += 10;
break;
case 38: // Up
top = Math.max(0, top - 10);
break;
case 40: // Down
top += 10;
break;
}
element.style.left = left + "px";
element.style.top = top + "px";
// Stop propagation and prevent default
event.stopPropagation();
event.preventDefault();
});
在那里,我们每次都重新获取元素,并且从
style
属性中解析现有的
left
和
top
值,这很好,因为键盘事件不会经常发生,但是没必要。理想情况下,您希望将所有代码放入“作用域函数”中,以免创建全局符号,如果这样做,我们只需获取一次元素,然后在事件处理程序中使用它,因为事件处理程序将create将是作用域函数上下文的闭包(不用担心,
closures are not complicated)。同样,我们可以在作用域函数中使用局部变量来跟踪
<div id="target"></div>
和
。所以:
(function() {
var element = document.getElementById("target"),
left = 0,
top = 0;
element.style.left = left + "px";
element.style.top = top + "px";
hookEvent(document, "keydown", function(event) {
switch (event.which || event.keyCode) {
case 37: // Left
left = Math.max(0, left - 10);
break;
case 39: // Right
left += 10;
break;
case 38: // Up
top = Math.max(0, top - 10);
break;
case 40: // Down
top += 10;
break;
}
element.style.left = left + "px";
element.style.top = top + "px";
// Stop propagation and prevent default
event.stopPropagation();
event.preventDefault();
});
})();
该代码必须在页面上的
之后,因为它假定该元素已经存在。
汇集所有
可运行的实时示例*(您必须单击框以确保该框具有焦点,然后按键才能起作用):
(function() {
// A cross-browser hook event function, tucked at the end to keep
// it out of the way
var hookEvent = makeHookEventFunction();
// Get the element, and our initial position
var element = document.getElementById("target"),
left = 0,
top = 0;
// Set the initial position on the element
element.style.left = left + "px";
element.style.top = top + "px";
// Handle the 'keydown' event
hookEvent(document, "keydown", function(event) {
// Work with 'which' or 'keyCode', whichever the browser gives us
switch (event.which || event.keyCode) {
case 37: // Left
left = Math.max(0, left - 10);
break;
case 39: // Right
left += 10;
break;
case 38: // Up
top = Math.max(0, top - 10);
break;
case 40: // Down
top += 10;
break;
default:
// Not for us
return;
}
// Update the element's position
element.style.left = left + "px";
element.style.top = top + "px";
// Since we've handled the key event, prevent it from
// propagating and prevent its default action
event.stopPropagation();
event.preventDefault();
});
// ------------------------------------------------------------
// A cross-browser "hook event" function, see my answer at
// https://stackoverflow.com/questions/23799296/js-li-tag-onclick-not-working-on-ie8/23799448#23799448
// for details.
function makeHookEventFunction() {
var div;
// The function we use on standard-compliant browsers
function standardHookEvent(element, eventName, handler) {
element.addEventListener(eventName, handler, false);
return element;
}
// The function we use on browsers with the previous Microsoft-specific mechanism
function oldIEHookEvent(element, eventName, handler) {
element.attachEvent("on" + eventName, function(e) {
e = e || window.event;
e.preventDefault = oldIEPreventDefault;
e.stopPropagation = oldIEStopPropagation;
handler.call(element, e);
});
return element;
}
// Polyfill for preventDefault on old IE
function oldIEPreventDefault() {
this.returnValue = false;
}
// Polyfill for stopPropagation on old IE
function oldIEStopPropagation() {
this.cancelBubble = true;
}
// Return the appropriate function; we don't rely on document.body
// here just in case someone wants to use this within the head
div = document.createElement('div');
if (div.addEventListener) {
div = undefined;
return standardHookEvent;
}
if (div.attachEvent) {
div = undefined;
return oldIEHookEvent;
}
throw "Neither modern event mechanism (addEventListener nor attachEvent) is supported by this browser.";
}
})();
#target {
position: absolute;
width: 10px;
/* Or whatever */
height: 10px;
/* Or whatever */
border: 1px solid black;
background-color: #ddd;
}
<div id="target"></div>
一些参考:
DOM2 Core
DOM2 HTML
DOM3 Core
HTML5 Specification
ECMAScript(JavaScript)规范:
Official PDF |
Handy HTML version
Mozilla's JavaScript pages
JavaScript:David Flanagan的权威指南
Crockford on JavaScript-乍一看可能不对,但一定要读一遍。他提出了许多优点。您可能不同意所有这些内容(我当然不同意),但是非常值得一读。
My anemic little blog-从最早的条目开始,然后继续前进,可能比Crockford更易访问-但权威性却低得多。
我是一名优秀的程序员,十分优秀!