• javascript 事件对象 坐标事件说明


    测试浏览器的版本: 

    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 { 

    7 //如果pageX属性为真 就使用pageX,否则就使用 clientX + html.scrollLeft 
    8 pageX : evt.pageX || evt.clientX + html.scrollLeft, 

    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') ); 
  • 相关阅读:
    fail to start File System Check
    qemu:///system 没有连接驱动器可用;读取数据时进入文件终点: 输入/输出错误
    [转载]libvirt(virsh命令总结)
    【转载】CentOS 7自动以root身份登录gnome桌面 操作系统开机后自动登录到桌面 跳过GDM
    Linux查看PCIe版本及速率# lspci -vvv |grep Width -i
    JAVA的线程能够在多个CPU上执行么?
    给定字典做分词
    POJ 3130 &amp; ZOJ 2820 How I Mathematician Wonder What You Are!(半平面相交 多边形是否有核)
    高仿一元云购IOS应用源代码项目
    增加收藏兼容主流浏览器代码
  • 原文地址:https://www.cnblogs.com/yangliulang/p/2765945.html
Copyright © 2020-2023  润新知