javascript 事件對象 座標事件說明

來源:互聯網
上載者:User

測試瀏覽器的版本:

IETester 6 ,7
IE 8.0
Firefox 3.5.5
Chrome 4.1.249.1064 (45376)
Opera 9.64
Safari 4.0

先來看看各個主流瀏覽器都有哪些座標屬性以及它們的意義

在IE中

event.offsetX
event.offsetY
相對於e.srcElement座標
設定或擷取滑鼠指標位置相對於觸發事件的對象的 x 座標。
設定或擷取滑鼠指標位置相對於觸發事件的對象的 y 座標。

event.clientX
event.clientY
總是相對於視口
設定或擷取滑鼠指標位置相對於視窗用戶端區域的 x 座標,其中用戶端區域不包括視窗自身的控制項和捲軸。
設定或擷取滑鼠指標位置相對於視窗用戶端區域的 y 座標,其中用戶端區域不包括視窗自身的控制項和捲軸。

event.x
event.y
雖然手冊上說是相對於文檔,但是ie6/7 中,他們倆的值跟clientX,clientY一致
但是這並不是嚴重的問題,因為視口相對座標加上捲軸已捲去高度,依然可以得到真實的x(y),這個問題在ie8的標準模式下被解決

設定或擷取滑鼠指標位置相對於父文檔的 x 像素座標。
設定或擷取滑鼠指標位置相對於父文檔的 y 像素座標。

event.screenX
event.screenY
設定或擷取擷取滑鼠指標位置相對於使用者螢幕的 x 座標。
設定或擷取擷取滑鼠指標位置相對於使用者螢幕的 y 座標。

在FireFox中

event.layerX
event.layerY
相對於e.srcElement座標
設定或擷取滑鼠指標位置相對於觸發事件的對象的 x 座標。
設定或擷取滑鼠指標位置相對於觸發事件的對象的 y 座標。

event.clientX
event.clientY
總是相對於視口
設定或擷取滑鼠指標位置相對於視窗用戶端區域的 x 座標,其中用戶端區域不包括視窗自身的控制項和捲軸。
設定或擷取滑鼠指標位置相對於視窗用戶端區域的 y 座標,其中用戶端區域不包括視窗自身的控制項和捲軸。

event.pageX
event.pageY
設定或擷取滑鼠指標位置相對於父文檔的 x 像素座標。
設定或擷取滑鼠指標位置相對於父文檔的 y 像素座標。

event.screenX
event.screenY
設定或擷取擷取滑鼠指標位置相對於使用者螢幕的 x 座標。
設定或擷取擷取滑鼠指標位置相對於使用者螢幕的 y 座標。

實際上IE和Firefox已經囊括了所有的屬性,其他的瀏覽器將這些屬性進行了組合,但是意義完全一致

Chrome 和 Safari
Chrome和Safari這哥倆辦事兒則灰常周全,它們收錄了所有的座標屬性,包括

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 的表現一致,它們和event.clientX,event.clientY相等

Opera堅定的走了ie6 7的道路,它擁有

event.offsetX
event.offsetY

event.clientX
event.clientY

event.x
event.y
差點就和ie一模一樣,幸好它有pageX,pageY
event.pageX
event.pageY

注意:Chrome和Safari,以及 Opera 的event.x event.y 都跟IE6 7 的表現一致,它們和event.clientX,event.clientY相等,
而在ie8中,event.x,event.y 則等同於 其他瀏覽器的event.pageX,event.pageY

為啥米layerX和offsetX, x,和pageX會在某些瀏覽器裡重複出現捏?
因為W3C並沒有標準化這些屬性,DOM3草案裡MouseEvent部分沿用了DOM2的定義,只有兩對屬性

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.

這下杯具了,所以支援標準的瀏覽器們都木有了方向,但是吧,瀏覽器廠商轉念一想,W3C反正也弄不出么蛾子來,肯定從offsetXY 和 layerXY,
pageXY 和 xy中間挑一個,於是為了迎合標準,就把這兩對屬性就都放進了瀏覽器中。

不管怎麼樣,出了問題總是要解決掉。看到上面的相容報告,代碼雛形也就做好了

我們開始動手寫!

getEventCoord 複製代碼 代碼如下:1 var getEventCoord = function( e )
2 {
3 var evt = e||event;
4 var html = document.documentElement; //捲軸在<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];
}

看起來已經灰常的OK,似乎已經能滿足日常工作需要了,但還是存在幾個問題

1.不嚴謹

使用 evt.pageX || evt.clientX + html.scrollLeft 這種判斷,
只要evt.pageX 等於 undefined,null,NaN,'',0,false 這些值,左邊的運算式結果就為false,從而計算右邊的運算式並返回運算式的值,
而evt.pageX本身就是有機會返回0的。所以這條判斷應該改為
typeof evt.pageX == 'number' ? evt.pageX : evt.clientX + html.scrollLeft
pageX是個數位時候我們才使用它

2.無法工作在怪異模式中

什麼是怪異模式?

IE為了相容IE56之前版本,在ie6中引入了兩種渲染模式: 怪異模式(Quicks Mode) 和 標準模式 (Standards Mode)
兩種模式差異主要集中在css的盒模型解釋方面,而BOM中。則是捲軸的依賴對象發生了變化
在怪異模式中,捲軸是body的,如果想取得頁面的滾動捲去的高度和寬度,需要使用document.body.scrollTop
而標準模式中需要使用document.documentElement.scrollTop

而兩種模式的切換方式主要是由doctype來確定,參見:http://dancewithnet.com/2009/06/14/activating-browser-modes-with-doctype/

從ie6開始,ie使用一個屬性 document.compatMode 來檢測文檔是否切換到了怪異模式還是處在標準模式
如果document.compatMode的值
為BackCompat:就是在怪癖模式下
為CSS1Compat:就是在標準模式下

所以這裡為了在兩個模式中都工作正常,
我們需要判斷document.compatMode是哪個模式
而判斷的方式也很簡單,只需要判斷compatMode的值的第一個字母是否為b,就可以選擇scrollTop的依賴對象
判斷方式可以這麼寫
document.compatMode.indexOf('b')==0
也可以用正則寫
/^b/i.test( document.compatMode )
第二種顯得更牛x一點。。嗯,就用第二種(實際上第一種效能好一點)

現在再來寫第二版吧

代碼 複製代碼 代碼如下: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
}
}

噔噔噔噔,這就搞定了,這個函數能幹啥哩,首先想到的就是拖拽,讓我們寫一個小小的拖拽函數驗證一下下

代碼 複製代碼 代碼如下: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') );

例子 <meta http-equiv="Content-Type" content="text/html; charset=gb2312"><br /><style> body { font-size:12px } #block { -moz-user-select:none; width:100px; height:100px; background:gray; color:white; line-height:100px; text-align:center; } .move { cursor:move; } </style>拖拽我<p>

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.