事件簡介
事件的三要素
事件的三要素:事件源、事件、事件驅(qū)動(dòng)程序。
- 事件源:引發(fā)后續(xù)事件的html標(biāo)簽。
- 事件:js已經(jīng)定義好了(見下圖)。
- 事件驅(qū)動(dòng)程序:對(duì)樣式和html的操作。也就是DOM。
也就是說,我們可以在時(shí)間對(duì)應(yīng)的屬性中寫一些js代碼,當(dāng)事件被觸發(fā)時(shí),這些代碼將會(huì)執(zhí)行。
代碼書寫步驟如下:(重要)
- (1)獲取事件源:document.getElementById(“box”); // 類似于Android里面的findViewById
- (2)綁定事件: 事件源box.事件onclick = function(){ 事件驅(qū)動(dòng)程序 };
- (3)書寫事件驅(qū)動(dòng)程序:關(guān)于DOM的操作。
最簡單的代碼舉例:(點(diǎn)擊box1,然后彈框)
<body>
<div id="box1"></div>
<script type="text/javascript">
// 1、獲取事件源
var div = document.getElementById("box1");
// 2、綁定事件
div.onclick = function () {
// 3、書寫事件驅(qū)動(dòng)程序
alert("我是彈出的內(nèi)容");
}
</script>
</body>
常見的事件如下:
下面針對(duì)這事件的三要素,進(jìn)行分別介紹。
1、獲取事件源的方式(DOM節(jié)點(diǎn)的獲?。?/h3>
獲取事件源的常見方式如下:
var div1 = document.getElementById("box1"); //方式一:通過id獲取單個(gè)標(biāo)簽
var arr1 = document.getElementsByTagName("div"); //方式二:通過 標(biāo)簽名 獲得 標(biāo)簽數(shù)組,所以有s
var arr2 = document.getElementsByClassName("hehe"); //方式三:通過 類名 獲得 標(biāo)簽數(shù)組,所以有s
2、綁定事件的方式
方式一:直接綁定匿名函數(shù)
<div id="box1" ></div>
<script type="text/javascript">
var div1 = document.getElementById("box1");
//綁定事件的第一種方式
div1.onclick = function () {
alert("我是彈出的內(nèi)容");
}
</script>
方式二:先單獨(dú)定義函數(shù),再綁定
<div id="box1" ></div>
<script type="text/javascript">
var div1 = document.getElementById("box1");
//綁定事件的第二種方式
div1.onclick = fn; //注意,這里是fn,不是fn()。fn()指的是返回值。
//單獨(dú)定義函數(shù)
function fn() {
alert("我是彈出的內(nèi)容");
}
</script>
注意上方代碼的注釋。綁定的時(shí)候,是寫fn,不是寫fn()。fn代表的是整個(gè)函數(shù),而fn()代表的是返回值。
方式三:行內(nèi)綁定
<!--行內(nèi)綁定-->
<div id="box1" onclick="fn()"></div>
<script type="text/javascript">
function fn() {
alert("我是彈出的內(nèi)容");
}
</script>
注意第一行代碼,綁定時(shí),是寫的"fn()"
,不是寫的"fn"
。因?yàn)榻壎ǖ倪@段代碼不是寫在js代碼里的,而是被識(shí)別成了字符串。
3、事件驅(qū)動(dòng)程序
我們在上面是拿alert舉例,不僅如此,我們還可以操作標(biāo)簽的屬性和樣式。舉例如下:
點(diǎn)擊鼠標(biāo)時(shí),原本粉色的div變大了,背景變紅:
<style>
#box1 {
width: 100px;
height: 100px;
background-color: pink;
cursor: pointer;
}
</style>
</head>
<body>
<div id="box1" ></div>
<script type="text/javascript">
var div1 = document.getElementById("box1");
//點(diǎn)擊鼠標(biāo)時(shí),原本粉色的div變大了,背景變紅了
div1.onclick = function () {
div1.style.width = "200px"; //屬性值要寫引號(hào)
div1.style.height = "200px";
div1.style.backgroundColor = "red"; //屬性名是backgroundColor,不是background-color
}
</script>
上方代碼的注意事項(xiàng):
- 在js里寫屬性值時(shí),要用引號(hào)
- 在js里寫屬性名時(shí),是
backgroundColor
,不是CSS里面的background-color
。
綁定事件的兩種方式/DOM事件的級(jí)別
DOM0的寫法:onclick
element.onclick = function () {
}
舉例:
<body>
<button>點(diǎn)我</button>
<script>
var btn = document.getElementsByTagName("button")[0];
//這種事件綁定的方式,如果綁定多個(gè),則后面的會(huì)覆蓋掉前面的
btn.onclick = function () {
console.log("事件1");
}
btn.onclick = function () {
console.log("事件2");
}
</script>
</body>
點(diǎn)擊按鈕后,上方代碼的打印結(jié)果:
事件2
我們可以看到,DOM對(duì)象.事件 = 函數(shù)
的這種綁定事件的方式:一個(gè)元素的一個(gè)事件只能綁定一個(gè)響應(yīng)函數(shù)。如果綁定了多個(gè)響應(yīng)函數(shù),則后者會(huì)覆蓋前者。
DOM2的寫法:addEventListener(高版本瀏覽器)
element.addEventListener('click', function () {
}, false);
參數(shù)解釋:
- 參數(shù)1:事件名的字符串(注意,沒有on)
- 參數(shù)2:回調(diào)函數(shù):當(dāng)事件觸發(fā)時(shí),該函數(shù)會(huì)被執(zhí)行
- 參數(shù)3:true表示捕獲階段觸發(fā),false表示冒泡階段觸發(fā)(默認(rèn))。如果不寫,則默認(rèn)為false。【重要】
舉例:
<body>
<button>按鈕</button>
<script>
var btn = document.getElementsByTagName("button")[0];
// addEventListener: 事件監(jiān)聽器。 原事件被執(zhí)行的時(shí)候,后面綁定的事件照樣被執(zhí)行
// 這種寫法不存在響應(yīng)函數(shù)被覆蓋的情況。(更適合團(tuán)隊(duì)開發(fā))
btn.addEventListener("click", fn1);
btn.addEventListener("click", fn2);
function fn1() {
console.log("事件1");
}
function fn2() {
console.log("事件2");
}
</script>
</body>
點(diǎn)擊按鈕后,上方代碼的打印結(jié)果:
事件1
事件2
我們可以看到,addEventListener()
這種綁定事件的方式:
- 一個(gè)元素的一個(gè)事件,可以綁定多個(gè)響應(yīng)函數(shù)。不存在響應(yīng)函數(shù)被覆蓋的情況。執(zhí)行順序是:事件被觸發(fā)時(shí),響應(yīng)函數(shù)會(huì)按照函數(shù)的綁定順序執(zhí)行。
- addEventListener()中的this,是綁定事件的對(duì)象。
-
addEventListener()
不支持 IE8 及以下的瀏覽器。在IE8中可以使用attachEvent
來綁定事件(詳見下一小段)。
DOM2的寫法:attachEvent(IE8及以下版本瀏覽器)
element.attachEvent('onclick', function () {
});
參數(shù)解釋:
- 參數(shù)1:事件名的字符串(注意,有on)
- 參數(shù)2:回調(diào)函數(shù):當(dāng)事件觸發(fā)時(shí),該函數(shù)會(huì)被執(zhí)行
舉例:
<body>
<button>按鈕</button>
<script>
var btn = document.getElementsByTagName('button')[0];
btn.attachEvent('onclick', function() {
console.log('事件1');
});
btn.attachEvent('onclick', function() {
console.log('事件2');
});
</script>
</body>
在低版本的IE瀏覽器上,點(diǎn)擊按鈕后,上方代碼的打印結(jié)果:
事件2
事件1
我們可以看到,attachEvent()
這種綁定事件的方式:
- 一個(gè)元素的一個(gè)事件,可以綁定多個(gè)響應(yīng)函數(shù)。不存在響應(yīng)函數(shù)被覆蓋的情況。注意:執(zhí)行順序是,后綁定的先執(zhí)行。
- attachEvent()中的this,是window
兼容性寫法
上面的內(nèi)容里,需要強(qiáng)調(diào)的是:
-
addEventListener()
中的this,是綁定事件的對(duì)象。 -
attachEvent()
中的this,是window。
既然這兩個(gè)寫法的this
不同,那么,有沒有一種兼容性的寫法可以確保這兩種綁定方式的this是相同的呢?我們可以封裝一下。代碼如下:
<body>
<button>按鈕</button>
<script>
var btn = document.getElementsByTagName('button')[0];
myBind(btn , "click" , function(){
alert(this);
});
//定義一個(gè)函數(shù),用來為指定元素綁定響應(yīng)函數(shù)
/*
* addEventListener()中的this,是綁定事件的對(duì)象
* attachEvent()中的this,是window
* 需要統(tǒng)一兩個(gè)方法this
*/
/*
* 參數(shù):
* element 要綁定事件的對(duì)象
* eventStr 事件的字符串(不要on)
* callback 回調(diào)函數(shù)
*/
function myBind(element , eventStr , callback){
if(element.addEventListener){
//大部分瀏覽器兼容的方式
element.addEventListener(eventStr , callback , false);
}else{
/*
* this是誰,由調(diào)用方式?jīng)Q定
* callback.call(element)
*/
//IE8及以下
element.attachEvent("on"+eventStr , function(){
//在匿名函數(shù) function 中調(diào)用回調(diào)函數(shù)callback
callback.call(element);
});
}
}
</script>
</body>
事件對(duì)象
當(dāng)事件的響應(yīng)函數(shù)被觸發(fā)時(shí),會(huì)產(chǎn)生一個(gè)事件對(duì)象event
。瀏覽器每次都會(huì)將這個(gè)事件event
作為實(shí)參傳進(jìn)之前的響應(yīng)函數(shù)。
這個(gè)對(duì)象中包含了與當(dāng)前事件相關(guān)的一切信息。比如鼠標(biāo)的坐標(biāo)、鍵盤的哪個(gè)按鍵被按下、鼠標(biāo)滾輪滾動(dòng)的方向等。
獲取 event 對(duì)象(兼容性問題)
所有瀏覽器都支持event對(duì)象,但支持的方式不同。如下。
(1)普通瀏覽器的寫法是 event
。比如:
(2)ie 678 的寫法是 window.event
。此時(shí),事件對(duì)象 event 是作為window對(duì)象的屬性保存的。
于是,我們可以采取一種兼容性的寫法。如下:
event = event || window.event; // 兼容性寫法
代碼舉例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script>
//點(diǎn)擊頁面的任何部分
document.onclick = function (event) {
event = event || window.event; ////兼容性寫法
console.log(event);
console.log(event.timeStamp);
console.log(event.bubbles);
console.log(event.button);
console.log(event.pageX);
console.log(event.pageY);
console.log(event.screenX);
console.log(event.screenY);
console.log(event.target);
console.log(event.type);
console.log(event.clientX);
console.log(event.clientY);
}
</script>
</body>
</html>
event 屬性
event 有很多屬性,比如:
由于pageX 和 pageY的兼容性不好,我們可以這樣做:
- 鼠標(biāo)在頁面的位置 = 滾動(dòng)條滾動(dòng)的距離 + 可視區(qū)域的坐標(biāo)。
使 div 跟隨鼠標(biāo)移動(dòng)
代碼實(shí)現(xiàn):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title></title>
<style type="text/css">
#box1 {
width: 100px;
height: 100px;
background-color: red;
/*
* 開啟box1的絕對(duì)定位
*/
position: absolute;
}
</style>
<script type="text/javascript">
window.onload = function() {
/*
* 使div可以跟隨鼠標(biāo)移動(dòng)
*/
//獲取box1
var box1 = document.getElementById("box1");
//給整個(gè)頁面綁定:鼠標(biāo)移動(dòng)事件
document.onmousemove = function(event) {
//兼容的方式獲取event對(duì)象
event = event || window.event;
// 鼠標(biāo)在頁面的位置 = 滾動(dòng)條滾動(dòng)的距離 + 可視區(qū)域的坐標(biāo)。
var pagex = event.pageX || scroll().left + event.clientX;
var pagey = event.pageY || scroll().top + event.clientY;
// 設(shè)置div的偏移量(相對(duì)于整個(gè)頁面)
// 注意,如果想通過 style.left 來設(shè)置屬性,一定要給 box1開啟絕對(duì)定位。
box1.style.left = pagex + "px";
box1.style.top = pagey + "px";
};
};
// scroll 函數(shù)封裝
function scroll() {
return {
//此函數(shù)的返回值是對(duì)象
left: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,
right:
window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft
};
}
</script>
</head>
<body style="height: 1000px;width: 2000px;">
<div id="box1"></div>
</body>
</html>
event.target 獲取的是觸發(fā)事件的標(biāo)簽元素
event.currentTarget 獲取到的是發(fā)起事件的標(biāo)簽元素
DOM事件流
事件傳播的三個(gè)階段是:事件捕獲、事件冒泡和目標(biāo)。
- 事件捕獲階段:事件從祖先元素往子元素查找(DOM樹結(jié)構(gòu)),直到捕獲到事件目標(biāo) target。在這個(gè)過程中,默認(rèn)情況下,事件相應(yīng)的監(jiān)聽函數(shù)是不會(huì)被觸發(fā)的。
- 事件目標(biāo):當(dāng)?shù)竭_(dá)目標(biāo)元素之后,執(zhí)行目標(biāo)元素該事件相應(yīng)的處理函數(shù)。如果沒有綁定監(jiān)聽函數(shù),那就不執(zhí)行。
- 事件冒泡階段:事件從事件目標(biāo) target 開始,從子元素往冒泡祖先元素冒泡,直到頁面的最上一級(jí)標(biāo)簽。
如下圖所示:
PS:這個(gè)概念類似于 Android 里的 touch 事件傳遞。
事件捕獲
addEventListener可以捕獲事件:
box1.addEventListener("click", function () {
alert("捕獲 box3");
}, true);
上面的方法中,參數(shù)為true,代表事件在捕獲階段執(zhí)行。
重點(diǎn):捕獲階段,事件依次傳遞的順序是:window --> document --> html--> body --> 父元素、子元素、目標(biāo)元素。
這幾個(gè)元素在事件捕獲階段的完整寫法是:
window.addEventListener("click", function () {
alert("捕獲 window");
}, true);
document.addEventListener("click", function () {
alert("捕獲 document");
}, true);
document.documentElement.addEventListener("click", function () {
alert("捕獲 html");
}, true);
document.body.addEventListener("click", function () {
alert("捕獲 body");
}, true);
fatherBox.addEventListener("click", function () {
alert("捕獲 father");
}, true);
childBox.addEventListener("click", function () {
alert("捕獲 child");
}, true);
說明:
(1)第一個(gè)接收到事件的對(duì)象是 window(有人會(huì)說body,有人會(huì)說html,這都是錯(cuò)誤的)。
(2)JS中涉及到DOM對(duì)象時(shí),有兩個(gè)對(duì)象最常用:window、doucument。它們倆是最先獲取到事件的。
補(bǔ)充一個(gè)知識(shí)點(diǎn):
在 js中:
- 如果想獲取
html
節(jié)點(diǎn),方法是document.documentElement
。 - 如果想獲取
body
節(jié)點(diǎn),方法是:document.body
。
二者不要混淆了。
事件冒泡
事件冒泡: 當(dāng)一個(gè)元素上的事件被觸發(fā)的時(shí)候(比如說鼠標(biāo)點(diǎn)擊了一個(gè)按鈕),同樣的事件將會(huì)在那個(gè)元素的所有祖先元素中被觸發(fā)。這一過程被稱為事件冒泡;這個(gè)事件從原始元素開始一直冒泡到DOM樹的最上層。
通俗來講,冒泡指的是:子元素的事件被觸發(fā)時(shí),父元素的同樣的事件也會(huì)被觸發(fā)。取消冒泡就是取消這種機(jī)制。
冒泡順序:
一般的瀏覽器: (除IE6.0之外的瀏覽器)
- div -> body -> html -> document -> window
IE6.0:
- div -> body -> html -> document
不是所有的事件都能冒泡
以下事件不冒泡:blur、focus、load、unload、onmouseenter、onmouseleave。意思是,事件不會(huì)往父元素那里傳遞。
我們檢查一個(gè)元素是否會(huì)冒泡,可以通過事件的以下參數(shù):
event.bubbles
如果返回值為true,說明該事件會(huì)冒泡;反之則相反。
舉例:
box1.onclick = function (event) {
alert("冒泡 child");
event = event || window.event;
console.log(event.bubbles); //打印結(jié)果:true。說明 onclick 事件是可以冒泡的
}
阻止冒泡
大部分情況下,冒泡都是有益的。當(dāng)然,如果你想阻止冒泡,也是可以的??梢园聪旅娴姆椒ㄗ柚姑芭?。
阻止冒泡的方法
w3c的方法:(火狐、谷歌、IE11)
event.stopPropagation();
IE10以下則是:
event.cancelBubble = true
兼容代碼如下:
box3.onclick = function (event) {
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
上方代碼中,我們對(duì)box3進(jìn)行了阻止冒泡,產(chǎn)生的效果是:事件不會(huì)繼續(xù)傳遞到 father、grandfather、body了。
事件委托
事件委托,通俗地來講,就是把一個(gè)元素響應(yīng)事件(click、keydown......)的函數(shù)委托到另一個(gè)元素。
比如說有一個(gè)列表 ul,列表之中有大量的列表項(xiàng) <a>
標(biāo)簽:
<ul id="parent-list">
<li><a href="javascript:;" class="my_link">超鏈接一</a></li>
<li><a href="javascript:;" class="my_link">超鏈接二</a></li>
<li><a href="javascript:;" class="my_link">超鏈接三</a></li>
</ul>
當(dāng)我們的鼠標(biāo)移到<a>
標(biāo)簽上的時(shí)候,需要獲取此<a>
的相關(guān)信息并飄出懸浮窗以顯示詳細(xì)信息,或者當(dāng)某個(gè)<a>
被點(diǎn)擊的時(shí)候需要觸發(fā)相應(yīng)的處理事件。我們通常的寫法,是為每個(gè)<a>
都綁定類似onMouseOver或者onClick之類的事件監(jiān)聽:
window.onload = function(){
var parentNode = document.getElementById("parent-list");
var aNodes = parentNode.getElementByTagName("a");
for(var i=0, l = aNodes.length; i < l; i++){
aNodes[i].onclick = function() {
console.log('我是超鏈接 a 的單擊相應(yīng)函數(shù)');
}
}
}
但是,上面的做法過于消耗內(nèi)存和性能。我們希望,只綁定一次事件,即可應(yīng)用到多個(gè)元素上,即使元素是后來添加的。
因此,比較好的方法就是把這個(gè)點(diǎn)擊事件綁定到他的父層,也就是 ul
上,然后在執(zhí)行事件函數(shù)的時(shí)候再去匹配判斷目標(biāo)元素。如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript">
window.onload = function() {
// 獲取父節(jié)點(diǎn),并為它綁定click單擊事件。 false 表示事件在冒泡階段觸發(fā)(默認(rèn))
document.getElementById('parent-list').addEventListener('click', function(event) {
event = event || window.event;
// e.target 表示:觸發(fā)事件的對(duì)象
//如果觸發(fā)事件的對(duì)象是我們期望的元素,則執(zhí)行否則不執(zhí)行
if (event.target && event.target.className == 'link') {
// 或者寫成 if (event.target && event.target.nodeName.toUpperCase() == 'A') {
console.log('我是ul的單擊響應(yīng)函數(shù)');
}
}, false);
};
</script>
</head>
<body>
<ul id="parent-list" style="background-color: #bfa;">
<li>
<p>我是p元素</p>
</li>
<li><a href="javascript:;" class="link">超鏈接一</a></li>
<li><a href="javascript:;" class="link">超鏈接二</a></li>
<li><a href="javascript:;" class="link">超鏈接三</a></li>
</ul>
</body>
上方代碼,為父節(jié)點(diǎn)注冊 click 事件,當(dāng)子節(jié)點(diǎn)被點(diǎn)擊的時(shí)候,click事件會(huì)從子節(jié)點(diǎn)開始向父節(jié)點(diǎn)冒泡。父節(jié)點(diǎn)捕獲到事件之后,開始執(zhí)行方法體里的內(nèi)容:通過判斷 event.target 拿到了被點(diǎn)擊的子節(jié)點(diǎn)<a>
。從而可以獲取到相應(yīng)的信息,并作處理。
換而言之,參數(shù)為false,說明事件是在冒泡階段觸發(fā)(子元素向父元素傳遞事件)。而父節(jié)點(diǎn)注冊了事件函數(shù),子節(jié)點(diǎn)沒有注冊事件函數(shù),此時(shí),會(huì)在父節(jié)點(diǎn)中執(zhí)行函數(shù)體里的代碼。
總結(jié):事件委托是利用了冒泡機(jī)制,減少了事件綁定的次數(shù),減少內(nèi)存消耗,提高性能。
鼠標(biāo)的拖拽事件
拖拽的流程:
(1)onmousedown
:當(dāng)鼠標(biāo)在被拖拽元素上按下時(shí),開始拖拽;
(2)onmousemove
:當(dāng)鼠標(biāo)移動(dòng)時(shí)被拖拽元素跟隨鼠標(biāo)移動(dòng);
(3)onmouseup
:當(dāng)鼠標(biāo)松開時(shí),被拖拽元素固定在當(dāng)前位置。
鼠標(biāo)的滾輪事件
onmousewheel
:鼠標(biāo)滾輪滾動(dòng)的事件,會(huì)在滾輪滾動(dòng)時(shí)觸發(fā)。但是火狐不支持該屬性。
DOMMouseScroll
:在火狐中需要使用 DOMMouseScroll 來綁定滾動(dòng)事件。注意該事件需要通過addEventListener()函數(shù)來綁定。
鍵盤事件
事件名
onkeydown
:按鍵被按下。
onkeyup
:按鍵被松開。
注意:
- 如果一直按著某一個(gè)按鍵不松手,那么,
onkeydown
事件會(huì)一直觸發(fā)。此時(shí),松開鍵盤,onkeyup
事件會(huì)執(zhí)行一次。 - 當(dāng)
onkeydown
連續(xù)觸發(fā)時(shí),第一次和第二次之間會(huì)間隔稍微長一點(diǎn),后續(xù)的間隔會(huì)非常快。這種設(shè)計(jì)是為了防止誤操作的發(fā)生。
鍵盤事件一般都會(huì)綁定給一些可以獲取到焦點(diǎn)的對(duì)象或者是document。代碼舉例:
<body>
<script>
document.onkeydown = function(event) {
event = event || window.event;
console.log('qianguyihao 鍵盤按下了');
};
document.onkeyup = function() {
console.log('qianguyihao 鍵盤松開了');
};
</script>
<input type="text" />
</body>
判斷哪個(gè)鍵盤被按下
可以通過event
事件對(duì)象的keyCode
來獲取按鍵的編碼。
此外,event
事件對(duì)象里面還提供了以下幾個(gè)屬性:
- altKey
- ctrlKey
- shiftKey
上面這三個(gè)屬性,可以用來判斷alt
、ctrl
、和shift
是否被按下。如果按下則返回true,否則返回false。代碼舉例:
<body>
<script>
document.onkeydown = function(event) {
event = event || window.event;
console.log('qianguyihao:鍵盤按下了');
// 判斷y和ctrl是否同時(shí)被按下
if (event.ctrlKey && event.keyCode === 89) {
console.log('ctrl和y都被按下了');
}
};
</script>
</body>
舉例:input 文本框中,禁止輸入數(shù)字。代碼實(shí)現(xiàn):
<body>
<input type="text" />
<script>
//獲取input
var input = document.getElementsByTagName('input')[0];
input.onkeydown = function(event) {
event = event || window.event;
//console.log('qianguyihao:' + event.keyCode);
//數(shù)字 48 - 57
//使文本框中不能輸入數(shù)字
if (event.keyCode >= 48 && event.keyCode <= 57) {
//在文本框中輸入內(nèi)容,屬于onkeydown的默認(rèn)行為
return false; // 如果在onkeydown中取消了默認(rèn)行為,則輸入的內(nèi)容,不會(huì)出現(xiàn)在文本框中
}
};
</script>
</body>
舉例:通過鍵盤的方向鍵,移動(dòng)盒子
代碼實(shí)現(xiàn):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title></title>
<style type="text/css">
#box1 {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
</head>
<body>
<div id="box1"></div>
<script type="text/javascript">
// 使div可以根據(jù)不同的方向鍵向不同的方向移動(dòng)
/*
* 按左鍵,div向左移
* 按右鍵,div向右移
* ...
*/
//為document綁定一個(gè)按鍵按下的事件
document.onkeydown = function(event) {
event = event || window.event;
//定義一個(gè)變量,來表示移動(dòng)的速度
var speed = 10;
//當(dāng)用戶按了ctrl以后,速度加快
if (event.ctrlKey) {
console.log('smyhvae ctrl');
speed = 20;
}
/*
* 37 左
* 38 上
* 39 右
* 40 下
*/
switch (event.keyCode) {
case 37:
//alert("向左"); left值減小
box1.style.left = box1.offsetLeft - speed + 'px'; // 在初始值的基礎(chǔ)之上,減去 speed 大小
break;
case 39:
//alert("向右");
box1.style.left = box1.offsetLeft + speed + 'px';
break;
case 38:
//alert("向上");
box1.style.top = box1.offsetTop - speed + 'px';
break;
case 40:
//alert("向下");
box1.style.top = box1.offsetTop + speed + 'px';
break;
}
};
</script>
</body>
</html>
上方代碼,待改進(jìn)的地方:
(1)移動(dòng)盒子時(shí),如果要加速,需要先按方向鍵
,再按Ctrl鍵
。
(2)首次移動(dòng)盒子時(shí),動(dòng)作較慢。后續(xù)如果學(xué)習(xí)了定時(shí)器相關(guān)的內(nèi)容,可以再改進(jìn)。