javascript 事件對(duì)象 坐標(biāo)事件說(shuō)明
IETester 6 ,7
IE 8.0
Firefox 3.5.5
Chrome 4.1.249.1064 (45376)
Opera 9.64
Safari 4.0
先來(lái)看看各個(gè)主流瀏覽器都有哪些坐標(biāo)屬性以及它們的意義
在IE中
event.offsetX
event.offsetY
相對(duì)于e.srcElement坐標(biāo)
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于觸發(fā)事件的對(duì)象的 x 坐標(biāo)。
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于觸發(fā)事件的對(duì)象的 y 坐標(biāo)。
event.clientX
event.clientY
總是相對(duì)于視口
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于窗口客戶區(qū)域的 x 坐標(biāo),其中客戶區(qū)域不包括窗口自身的控件和滾動(dòng)條。
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于窗口客戶區(qū)域的 y 坐標(biāo),其中客戶區(qū)域不包括窗口自身的控件和滾動(dòng)條。
event.x
event.y
雖然手冊(cè)上說(shuō)是相對(duì)于文檔,但是ie6/7 中,他們倆的值跟clientX,clientY一致
但是這并不是嚴(yán)重的問(wèn)題,因?yàn)橐暱谙鄬?duì)坐標(biāo)加上滾動(dòng)條已卷去高度,依然可以得到真實(shí)的x(y),這個(gè)問(wèn)題在ie8的標(biāo)準(zhǔn)模式下被解決
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于父文檔的 x 像素坐標(biāo)。
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于父文檔的 y 像素坐標(biāo)。
event.screenX
event.screenY
設(shè)置或獲取獲取鼠標(biāo)指針位置相對(duì)于用戶屏幕的 x 坐標(biāo)。
設(shè)置或獲取獲取鼠標(biāo)指針位置相對(duì)于用戶屏幕的 y 坐標(biāo)。
在FireFox中
event.layerX
event.layerY
相對(duì)于e.srcElement坐標(biāo)
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于觸發(fā)事件的對(duì)象的 x 坐標(biāo)。
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于觸發(fā)事件的對(duì)象的 y 坐標(biāo)。
event.clientX
event.clientY
總是相對(duì)于視口
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于窗口客戶區(qū)域的 x 坐標(biāo),其中客戶區(qū)域不包括窗口自身的控件和滾動(dòng)條。
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于窗口客戶區(qū)域的 y 坐標(biāo),其中客戶區(qū)域不包括窗口自身的控件和滾動(dòng)條。
event.pageX
event.pageY
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于父文檔的 x 像素坐標(biāo)。
設(shè)置或獲取鼠標(biāo)指針位置相對(duì)于父文檔的 y 像素坐標(biāo)。
event.screenX
event.screenY
設(shè)置或獲取獲取鼠標(biāo)指針位置相對(duì)于用戶屏幕的 x 坐標(biāo)。
設(shè)置或獲取獲取鼠標(biāo)指針位置相對(duì)于用戶屏幕的 y 坐標(biāo)。
實(shí)際上IE和Firefox已經(jīng)囊括了所有的屬性,其他的瀏覽器將這些屬性進(jìn)行了組合,但是意義完全一致
Chrome 和 Safari
Chrome和Safari這哥倆辦事兒則灰常周全,它們收錄了所有的坐標(biāo)屬性,包括
event.offsetX
event.offsetY
event.layerX
event.layerY
event.clientX
event.clientY
event.x
event.y
event.pageX
event.pageY
注意:Chrome和Safari的event.x event.y 跟IE6 7 的表現(xiàn)一致,它們和event.clientX,event.clientY相等
Opera堅(jiān)定的走了ie6 7的道路,它擁有
event.offsetX
event.offsetY
event.clientX
event.clientY
event.x
event.y
差點(diǎn)就和ie一模一樣,幸好它有pageX,pageY
event.pageX
event.pageY
注意:Chrome和Safari,以及 Opera 的event.x event.y 都跟IE6 7 的表現(xiàn)一致,它們和event.clientX,event.clientY相等,
而在ie8中,event.x,event.y 則等同于 其他瀏覽器的event.pageX,event.pageY
為啥米layerX和offsetX, x,和pageX會(huì)在某些瀏覽器里重復(fù)出現(xiàn)捏?
因?yàn)閃3C并沒(méi)有標(biāo)準(zhǔn)化這些屬性,DOM3草案里MouseEvent部分沿用了DOM2的定義,只有兩對(duì)屬性
clientX of type long, readonly
The horizontal coordinate at which the event occurred relative to the viewport associated with the event.
clientY of type long, readonly
The vertical coordinate at which the event occurred relative to the viewport associated with the event
screenX of type long, readonly
The horizontal coordinate at which the event occurred relative to the origin of the screen coordinate system.
screenY of type long, readonly
The vertical coordinate at which the event occurred relative to the origin of the screen coordinate system.
這下杯具了,所以支持標(biāo)準(zhǔn)的瀏覽器們都木有了方向,但是吧,瀏覽器廠商轉(zhuǎn)念一想,W3C反正也弄不出幺蛾子來(lái),肯定從offsetXY 和 layerXY,
pageXY 和 xy中間挑一個(gè),于是為了迎合標(biāo)準(zhǔn),就把這兩對(duì)屬性就都放進(jìn)了瀏覽器中。
不管怎么樣,出了問(wèn)題總是要解決掉。看到上面的兼容報(bào)告,代碼雛形也就做好了
我們開(kāi)始動(dòng)手寫(xiě)!
getEventCoord
1 var getEventCoord = function( e )
2 {
3 var evt = e||event;
4 var html = document.documentElement; //滾動(dòng)條在<HTML>上
5 return {
6
7 //如果pageX屬性為真 就使用pageX,否則就使用 clientX + html.scrollLeft
8 pageX : evt.pageX || evt.clientX + html.scrollLeft,
9
10 //如果pageY屬性為真 就使用pageY,否則就使用 clientY + html.scrollTop
11 pageY : evt.pageY || evt.clientY + html.scrollTop,
12
13 //clientX Y 大家都一致,木有懸念
14 clientX : evt.clientX,
15 clientY : evt.clientY,
16
17 //如果layerX屬性為真 就使用layerX,否則就使用 offsetX
18 layerX : evt.layerX || evt.offsetX,
19
20 //如果layerY屬性為真 就使用layerY,否則就使用 offsetY
21 layerY : evt.layerY || evt.offsetY
22 }
23 }
用法如下
document.onmousemove = function( e )
{
var coord = getEventCoord(e);
document.title = [coord.pageX,coord.pageY];
}
看起來(lái)已經(jīng)灰常的OK,似乎已經(jīng)能滿足日常工作需要了,但還是存在幾個(gè)問(wèn)題
1.不嚴(yán)謹(jǐn)
使用 evt.pageX || evt.clientX + html.scrollLeft 這種判斷,
只要evt.pageX 等于 undefined,null,NaN,'',0,false 這些值,左邊的表達(dá)式結(jié)果就為false,從而計(jì)算右邊的表達(dá)式并返回表達(dá)式的值,
而evt.pageX本身就是有機(jī)會(huì)返回0的。所以這條判斷應(yīng)該改為
typeof evt.pageX == 'number' ? evt.pageX : evt.clientX + html.scrollLeft
pageX是個(gè)數(shù)字的時(shí)候我們才使用它
2.無(wú)法工作在怪異模式中
什么是怪異模式?
IE為了兼容IE56之前版本,在ie6中引入了兩種渲染模式: 怪異模式(Quicks Mode) 和 標(biāo)準(zhǔn)模式 (Standards Mode)
兩種模式差異主要集中在css的盒模型解釋方面,而B(niǎo)OM中。則是滾動(dòng)條的依賴對(duì)象發(fā)生了變化
在怪異模式中,滾動(dòng)條是body的,如果想取得頁(yè)面的滾動(dòng)卷去的高度和寬度,需要使用document.body.scrollTop
而標(biāo)準(zhǔn)模式中需要使用document.documentElement.scrollTop
而兩種模式的切換方式主要是由doctype來(lái)確定,參見(jiàn):http://dancewithnet.com/2009/06/14/activating-browser-modes-with-doctype/
從ie6開(kāi)始,ie使用一個(gè)屬性 document.compatMode 來(lái)檢測(cè)文檔是否切換到了怪異模式還是處在標(biāo)準(zhǔn)模式
如果document.compatMode的值
為BackCompat:就是在怪癖模式下
為CSS1Compat:就是在標(biāo)準(zhǔn)模式下
所以這里為了在兩個(gè)模式中都工作正常,
我們需要判斷document.compatMode是哪個(gè)模式
而判斷的方式也很簡(jiǎn)單,只需要判斷compatMode的值的第一個(gè)字母是否為b,就可以選擇scrollTop的依賴對(duì)象
判斷方式可以這么寫(xiě)
document.compatMode.indexOf('b')==0
也可以用正則寫(xiě)
/^b/i.test( document.compatMode )
第二種顯得更牛x一點(diǎn)。。嗯,就用第二種(實(shí)際上第一種性能好一點(diǎn))
現(xiàn)在再來(lái)寫(xiě)第二版吧
代碼
var getEventCoord = function( e )
{
var evt = e||event, d = document,
scrollEl = /^b/i.test( d.compatMode ) ? d.body : d.documentElement,
supportPage = typeof evt.pageX == 'number',
supportLayer = typeof evt.layerX == 'number'
return {
pageX : supportPage ? evt.pageX : evt.clientX + scrollEl.scrollLeft,
pageY : supportPage ? evt.pageY : evt.clientY + scrollEl.scrollTop,
clientX : evt.clientX,
clientY : evt.clientY,
layerX : supportLayer ? evt.layerX : evt.offsetX,
layerY : supportLayer ? evt.layerY : evt.offsetY
}
}
噔噔噔噔,這就搞定了,這個(gè)函數(shù)能干啥哩,首先想到的就是拖拽,讓我們寫(xiě)一個(gè)小小的拖拽函數(shù)驗(yàn)證一下下
代碼
function dragMe( o )
{
var supportCapt = !!o.setCapture;
o.onmousedown = function(e)
{
var coord = getEventCoord(e), x = coord.layerX, y = coord.layerY;
if( supportCapt ) o.setCapture();
document.onmousemove = function(e)
{
var coord = getEventCoord(e);
o.style.left = coord.pageX - x + 'px';
o.style.top = coord.pageY - y + 'px';
}
document.onmouseup = function()
{
this.onmousemove = this.onmouseup = null;
if( supportCapt ) o.releaseCapture();
}
}
}
dragMe( document.getElementById('block') );
例子
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
相關(guān)文章
JS實(shí)現(xiàn)響應(yīng)鼠標(biāo)點(diǎn)擊動(dòng)畫(huà)漸變彈出層效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)響應(yīng)鼠標(biāo)點(diǎn)擊動(dòng)畫(huà)漸變彈出層效果代碼,具有非常自然流暢的動(dòng)畫(huà)過(guò)度效果,涉及JavaScript針對(duì)鼠標(biāo)事件的響應(yīng)及頁(yè)面元素樣式的動(dòng)態(tài)操作相關(guān)技巧,需要的朋友可以參考下2016-03-03javascript中直接引用Microsoft的COM生成Word
直接引用Microsoft的COM是可以生成Word的,下面為大家介紹下實(shí)現(xiàn)的javascript代碼2014-01-01javaScript之split與join的區(qū)別(詳解)
下面小編就為大家?guī)?lái)一篇javaScript之split與join的區(qū)別(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11JS小功能(列表頁(yè)面隔行變色)簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了JS列表頁(yè)面隔行變色簡(jiǎn)單實(shí)現(xiàn),有需要的朋友可以參考一下2013-11-11JavaScript實(shí)現(xiàn)簡(jiǎn)單打地鼠游戲
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單打地鼠游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10JavaScript中關(guān)于iframe滾動(dòng)條的去除和保留
在開(kāi)發(fā)中經(jīng)常遇到去掉全部的滾動(dòng)條,去掉右邊的滾動(dòng)條且保留底下的滾動(dòng)條,去掉底下的滾動(dòng)條且保留右邊的滾動(dòng)條,大家基于js是怎么實(shí)現(xiàn)的呢?下面小編通過(guò)本文給大家詳細(xì)介紹下,對(duì)js iframe滾動(dòng)條相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-11-11js+canvas實(shí)現(xiàn)畫(huà)板功能
這篇文章主要為大家詳細(xì)介紹了js+canvas實(shí)現(xiàn)畫(huà)板功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09JavaScript 字符串與數(shù)組轉(zhuǎn)換函數(shù)[不用split與join]
下面的代碼,不考慮他的運(yùn)行效率的話,思路不錯(cuò),大家可以看看,但在實(shí)際的應(yīng)用中,我們?nèi)匀皇褂胹plit或join來(lái)實(shí)現(xiàn)數(shù)組的操作。2009-12-12JS去除字符串的空格增強(qiáng)版(可以去除中間的空格)
之前發(fā)了不少了去除字符串空格的代碼,但都是去除開(kāi)始與結(jié)尾的,下面的這段代碼可以去除中間的。2009-08-08