JavaScript實(shí)現(xiàn)按鍵精靈的原理分析
最近有個(gè)需求,需要在頁(yè)面上面自動(dòng)點(diǎn)擊、輸入、提交。
用以模擬真實(shí)用戶的操作行為,可以通過(guò)直接執(zhí)行某個(gè)元素綁定的事件,來(lái)執(zhí)行操作。
也可以創(chuàng)建事件,再派發(fā)事件,執(zhí)行操作。關(guān)于事件的更多細(xì)節(jié),可以參考《JavaScript中事件處理》
1、模擬MouseEvent中的click事件,x與y位置隨機(jī)點(diǎn)擊
2、模擬TouchEvent中的touchstart和touchmove,用scroll來(lái)做滑動(dòng)效果
3、模擬FocusEvent,聚焦到屏幕中的輸入框內(nèi)

一、鼠標(biāo)事件MouseEvent
MouseEvent接口指用戶與指針設(shè)備( 如鼠標(biāo) )交互時(shí)發(fā)生的事件。使用此接口的常見(jiàn)事件包括:click,dblclick,mouseup,mousedown。
MouseEvent派生自 UIEvent,UIEvent 派生自 Event。
function random(max) {
return Math.floor(Math.random() * max);
}
function on(dom, type, fn) {
dom.addEventListener(type, fn, false);
}
on(document.body, 'click', function(e) {
console.log('click事件 x:'+e.clientX, 'y:'+e.clientY);
});
/**
* MouseEvent
* 包括事件 click,dblclick,mouseup,mousedown
*/
function mouse() {
var x = random(window.outerWidth),
y = random(window.outerHeight);
var event = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
clientX: x,
clientY: y
});
console.log('click環(huán)境 x:'+x, 'y:'+y);
document.body.dispatchEvent(event);
}
mouse();
1)Event
語(yǔ)法如下:

typeArg:事件的名字,DOMString類型。
eventInit:
|
屬性 |
選項(xiàng) | 默認(rèn) | 類型 | 描述 |
| bubbles | 可選 | false | Boolean | 事件是否冒泡 |
| cancelable | 可選 | false | Boolean | 事件是否可取消 |
| scoped | 可選 | Boolean | indicating whether the given event bubbles. If this value is true, deepPath will only contain a target node. | |
| composed | 可選 | false | Boolean |
事件是否會(huì)影子根(shadow root)之外觸發(fā)偵聽(tīng)器。 Shadow DOM是指在文檔(document)渲染時(shí)插入一棵DOM元素子樹(shù),但是這棵子樹(shù)不在主DOM樹(shù)中。 |
2)UIEvent
語(yǔ)法如下:
有多個(gè)事件對(duì)象直接或間接的繼承了UIEvent,包括:MouseEvent, TouchEvent, FocusEvent, KeyboardEvent, WheelEvent, InputEvent和CompositionEvent。
UIEventInit:
|
屬性 |
選項(xiàng) | 默認(rèn) | 類型 | 描述 |
| detail | 可選 | 0 | long長(zhǎng)整型 |
根據(jù)事件不同意義也會(huì)不同。 對(duì) click 或者 dblclick 事件, detail是當(dāng)前點(diǎn)擊數(shù)量; 對(duì)mousedown或者mouseup事件, detail是1加上當(dāng)前點(diǎn)擊數(shù); 對(duì)所有的其它UIEvent對(duì)象, detail總是0。 |
| view | 可選 | null | WindowProxy | 與事件相關(guān)聯(lián)的窗口 |
3)MouseEvent
語(yǔ)法如下:

mouseEventInit:
|
屬性 |
選項(xiàng) | 默認(rèn) | 類型 | 描述 |
| screenX/screenY | 可選 | 0 | long長(zhǎng)整型 |
鼠標(biāo)事件發(fā)生時(shí)相對(duì)于用戶屏幕screen的水平/垂直坐標(biāo)位置; 該操作并不會(huì)改變真實(shí)鼠標(biāo)的位置。 |
| clientX/clientY | 可選 | 0 | long長(zhǎng)整型 |
鼠標(biāo)事件時(shí)相對(duì)于瀏覽器窗口viewport的水平/垂直坐標(biāo)位置,不包含滾動(dòng)距離; 該操作并不會(huì)改變真實(shí)鼠標(biāo)的位置。 |
| ctrlKey | 可選 | false | Boolean | 按下了Ctrl鍵 |
| shiftKey | 可選 | false | Boolean | 按下了Shift鍵 |
| altKey | 可選 | false | Boolean | 按下了Alt鍵 |
| metaKey | 可選 | false | Boolean | 按下了Meta鍵 |
| button | 可選 | 0 | short短整型 |
當(dāng)事件發(fā)生時(shí)哪個(gè)按鍵被按下或釋放; 0:左鍵 1:中建 2:右鍵 |
| buttons | 可選 | 0 | 無(wú)符號(hào)short |
當(dāng)事件發(fā)生時(shí)哪些按鍵被按下; 0:無(wú)按鍵按下 1:左鍵 2:中建 4:右鍵 |
| relatedTarget | 可選 | null | EventTarget |
標(biāo)明剛離開(kāi)的元素 (發(fā)生在事件 mouseenter 或 mouseover); 或剛進(jìn)入的元素 (發(fā)生在事件 mouseout 或 mouseleave)。 |
| region | 可選 | null | DOMString | 點(diǎn)擊事件影響的區(qū)域DOM的id |
二、觸屏事件TouchEvent
TouchEvent是一類描述手指在觸摸平面(觸摸屏、觸摸板等)的狀態(tài)變化的事件。
每個(gè)Touch對(duì)象代表一個(gè)觸點(diǎn); 每個(gè)觸點(diǎn)都由其位置,大小,形狀,壓力大小,和目標(biāo)元素描述。TouchList對(duì)象代表多個(gè)觸點(diǎn)的一個(gè)列表。
觸屏touch事件的更多細(xì)節(jié),可以參加《觸屏touch事件記錄》
on(document.body, 'touchstart', function(e) {
var touch = e.touches.item(0);
console.log('touchstart x:' + touch.clientX, 'y:' + touch.clientY);
});
on(document.body, 'touchmove', function(e) {
var touch = e.touches.item(0);
console.log('touchmove x:' + touch.clientX, 'y:' + touch.clientY);
});
on(document.body, 'touchend', function(e) {
var touch = e.changedTouches.item(0);
console.log('touchend x:' + touch.clientX, 'y:' + touch.clientY);
});
on(window, 'scroll', function(e) {
console.log('scroll timestamp:' + e.timeStamp);
});
/**
* TouchEvent
* 包括事件 touchstart,touchend,touchmove,touchcancel
*/
function touchstart(x, y, number) {
var touch = new Touch({
identifier: number,
target: document.querySelector('.drag'), //隨便設(shè)置的
clientX: x,
clientY: y
});
console.log('touchstart環(huán)境 x:' + x, 'y:' + y);
var event = new TouchEvent('touchstart', {
touches: [touch],
targetTouches: [touch],
changedTouches: [touch]
});
document.body.dispatchEvent(event); //touchstart
}
function touchmove(x, y, interval, number) {
var touch = new Touch({
identifier: number,
target: document.querySelector('.drag'), //隨便設(shè)置的
clientX: x,
clientY: y + interval
});
var event = new TouchEvent('touchmove', {
touches: [touch],
targetTouches: [touch],
changedTouches: [touch]
});
document.body.dispatchEvent(event); //touchmove
}
function touch() {
var x = random(window.outerWidth),
y = random(window.outerHeight),
number = 1,
interval = 10;
touchstart(x, y, number);
number++;
touchmove(x, y, interval, number);
number++;
interval += 10;
touchmove(x, y, interval, number);
number++;
interval += 10;
touchmove(x, y, interval, number);
document.body.scrollTop = interval; //自動(dòng)滾動(dòng)
}
setTimeout(function() {
touch();
}, 2000);
1)Touch
語(yǔ)法如下:

touchInit:
|
屬性 |
選項(xiàng) | 默認(rèn) | 類型 | 描述 |
| identifier | 必填 | long長(zhǎng)整型 | 一個(gè)觸摸點(diǎn)的數(shù)字標(biāo)記,唯一標(biāo)識(shí)符。 | |
| target | 必填 | EventTarget | 觸點(diǎn)最開(kāi)始被跟蹤時(shí)(在 touchstart 事件中),位于的HTML元素。 | |
| clientX/clientY | 可選 | 0 | double | 觸摸點(diǎn)相對(duì)于瀏覽器窗口viewport的位置,不包含滾動(dòng)距離,這個(gè)值會(huì)根據(jù)用戶對(duì)可見(jiàn)視區(qū)的縮放行為而發(fā)生變化。 |
| screenX/screenY | 可選 | 0 | double |
觸摸點(diǎn)相對(duì)于屏幕screen的位置。在IOS中與clientX/clientY屬性不同,不會(huì)受到initial-scale的影響; 而在安卓中微信和UC會(huì)受之影響,而手機(jī)版chrome與紅米note自帶的瀏覽器不會(huì)被影響。 |
| pageX/pageY | 可選 | 0 | double | 和clientX/clientY屬性不同,這個(gè)值是相對(duì)于整個(gè)html文檔的坐標(biāo),這個(gè)值包含了垂直滾動(dòng)的偏移。 |
| radiusX/radiusY | 可選 | 0 | float | 能夠包圍用戶和觸摸平面的接觸面的最小橢圓的水平軸(X軸)/垂直軸(Y軸)半徑。 |
| rotationAngle | 可選 | 0 | float |
以度為單位的旋轉(zhuǎn)角,由radiusX和radiusY描述的正方向的橢圓; 通過(guò)順時(shí)針旋轉(zhuǎn)這個(gè)角度后,能最精確地覆蓋住用戶和觸摸平面的接觸面的角度。 |
| force | 可選 | 0 | float | 手指擠壓觸摸平面的壓力大小,從0.0(沒(méi)有壓力)到1.0(設(shè)備可識(shí)別的最大壓力)的浮點(diǎn)數(shù)。 |
2)TouchEvent
語(yǔ)法如下:

touchEventInit:
|
屬性 |
選項(xiàng) | 默認(rèn) | 類型 | 描述 |
| touches | 可選 | [] | TouchList | TouchList類型(包含了一系列Touch對(duì)象的數(shù)組),當(dāng)前位于屏幕上的所有手指的列表。 |
| targetTouches | 可選 | [] | TouchList | 與touches類似,但是增加了個(gè)過(guò)濾條件,要與第一個(gè)手指點(diǎn)的地方(同一個(gè)節(jié)點(diǎn)內(nèi))相同。 |
| changedTouches | 可選 | [] | TouchList |
在touchstart中:列出在此次事件中新增加的觸點(diǎn)。如果同時(shí)放下一根或兩根手指,那么將與touches相同,但如果先放一根,在放第二根,那就會(huì)不同。 在touchmove中:列出和上一次事件相比較,發(fā)生了變化的觸點(diǎn)。 在touchend中:列出離開(kāi)觸摸平面的觸點(diǎn)(這些觸點(diǎn)對(duì)應(yīng)已經(jīng)不接觸觸摸平面的手指)。 |
| ctrlKey | 可選 | false | Boolean | 按下了Ctrl鍵 |
| shiftKey | 可選 | false | Boolean | 按下了Shift鍵 |
| altKey | 可選 | false | Boolean | 按下了Alt鍵 |
| metaKey | 可選 | false | Boolean | 按下了Meta鍵 |
三、焦點(diǎn)事件FocusEvent
FocusEvent接口表示和焦點(diǎn)相關(guān)的事件比如 focus, blur, focusin, 和 focusout。
on(document.getElementById('txt'), 'focus', function(e) {
//console.log(e);
console.log('focus timestamp:' + e.timeStamp);
});
/**
* FocusEvent
* 包括事件 focus, blur, focusin, focusout
*/
function focus() {
var event = new FocusEvent('focus', {
view: window
});
document.getElementById('txt').dispatchEvent(event);
}
focus();
1)FocusEvent
語(yǔ)法如下:

focusEventInit:
屬性
源碼查看:
http://codepen.io/strick/pen/xgNGbz
以上所述是小編給大家介紹的JavaScript實(shí)現(xiàn)按鍵精靈的原理分析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
JS實(shí)現(xiàn)移動(dòng)端判斷上拉和下滑功能
通過(guò)手指觸屏,利用touchstart和touchend計(jì)算前后滑動(dòng)距離,判斷是上拉還是下滑。接下來(lái)通過(guò)實(shí)例代碼給大家介紹js移動(dòng)端判斷上拉和下滑功能,感興趣的朋友一起看看吧2017-08-08
JavaScript及jquey實(shí)現(xiàn)多個(gè)數(shù)組的合并操作
這篇文章主要介紹了JavaScript及jquey實(shí)現(xiàn)多個(gè)數(shù)組的合并操作,在某些情況下還是比較實(shí)用的,需要的朋友可以參考下2014-09-09
js使用for循環(huán)查詢數(shù)組中是否存在某個(gè)值
IE8不支持indexOf,因此寫一個(gè)for循環(huán)來(lái)判斷是否存在,下面是代碼,經(jīng)測(cè)試還不錯(cuò)2014-08-08
原生JS實(shí)現(xiàn)左右箭頭選擇日期實(shí)例代碼
原生JS 左右箭頭選擇日期,就是用左右尖括號(hào)可改變中間日期的值,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-03-03
js實(shí)現(xiàn)rem自動(dòng)匹配計(jì)算font-size的示例
本篇文章主要介紹了js實(shí)現(xiàn)rem自動(dòng)匹配計(jì)算font-size的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
js實(shí)現(xiàn)select二級(jí)聯(lián)動(dòng)下拉菜單
這個(gè)是簡(jiǎn)單也是最基本的下拉框聯(lián)動(dòng)的示例,這個(gè)示例主要針對(duì)那些只有二級(jí)聯(lián)動(dòng),且第一級(jí)是固定的選項(xiàng),第二級(jí)的內(nèi)容也比較簡(jiǎn)單,不刷新的聯(lián)動(dòng),感興趣的小伙伴們可以參考一下2016-04-04
KnockoutJS 3.X API 第四章之?dāng)?shù)據(jù)控制流component綁定
這篇文章主要介紹了KnockoutJS 3.X API 第四章之?dāng)?shù)據(jù)控制流component綁定的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10

