HTML坐标系与鼠标事件坐标

在开发中处理鼠标事件时,经常会碰到 offset、scroll、client 这几个关键字,每次处理页面元素的坐标和偏移前,都要网上去搜资料,还会踩一些坑,影响开发效率。这里总结一下,一劳永逸。

一、图解HTML的四个坐标系统

  HTML有四个常见的坐标系统:screen,page,client和offset,用于描述DOM元素的Box尺寸和MouseEvent中的位置。
  如下图所示:
图解html坐标系

点击这里查看大图

1. screen
  参照点:电脑屏幕左上角
  screenX:鼠标点击位置相对于电脑屏幕左上角的水平偏移量
  screenY:鼠标点击位置相对于电脑屏幕左上角的垂直偏移量
  screen坐标的最大范围是 (screen.width, screen.height)

  补充:

    // 屏幕宽度。
    screen.width
    // 屏幕高度。
    screen.height
    // 屏幕可用宽度。即屏幕宽度减去左右任务栏后的宽度,可表示为浏览器最大化时的宽度。
  screen.availWidth
    // 屏幕可用高度。即屏幕高度减去上下任务栏后的高度,可表示为浏览器最大化时的高度。
  screen.availHeight
    // 任务栏高/宽度。如:任务栏高/宽度 = 屏幕高/宽度 - 屏幕可用高/宽度。
  screen.height - screen.availHeight

2. page
  参照点:网页的左上角
  pageX:鼠标点击位置相对于网页左上角的水平偏移量,也就是clientX加上水平滚动条的距离
  pageY:鼠标点击位置相对于网页左上角的垂直平偏移量,也就是clientY加上垂直滚动条的距离
  page坐标的最大范围是 (window.innerWidth, window.innerHeight)

  补充:

    // 浏览器宽度。
    window.outerWidth
    // 浏览器高度。
    window.outerHeight
    // 浏览器内页面可用宽度,此宽度包含了垂直滚动条的宽度(若存在)。可表示为浏览器当前宽度去除浏览器边框后的宽度。
  window.innerWidth
    // 浏览器内页面可用高度,此高度包含了水平滚动条的高度(若存在)。可表示为浏览器当前高度去除浏览器边框、工具条后的高度。
  window.innerHeight
    // 工具栏高/宽度,包含了地址栏、书签栏、浏览器边框等范围。如:工具栏高度 = 浏览器高度 - 页面可用高度。
  window.outerHeight - window.innerHeight

3. client
  参照点:浏览器内容区域左上角
  clientX:鼠标点击位置相对于浏览器可视区域的水平偏移量(不会计算水平滚动的距离)
  clientY:鼠标点击位置相对于浏览器可视区域的垂直偏移量(不会计算垂直滚动条的距离)
  client坐标的最大范围是 (document.body.clientWidth, document.body.clientHeight)

  补充:

    // body展示的宽度,表示body在浏览器内显示的区域宽度。
    document.body.clientWidth
    // body展示的高度,表示body在浏览器内显示的区域高度。
    document.body.clientHeight
    // 滚动条高度/宽度,如:滚动条高度 = 浏览器内页面可用高度 - body展示高度。
    window.innerHeight - body.clientHeight

4. offset
  参照点:父级中最近的一个带有CSS定位(position为absolute/relative)的父元素,如果当前元素的父级元素中没有进行CSS定位,那么就是body
  offsetX:鼠标点击位置相对于触发事件对象的水平距离
  offsetY:鼠标点击位置相对于触发事件对象的垂直距离
  offset坐标的最大范围是 (document.body.offsetWidth, document.body.offsetHeight)

  补充:

    // body总宽度。
    document.body.offsetWidth
    // body总高度。
    document.body.offsetHeight

二、图解鼠标事件坐标

  鼠标事件都是在特定位置发生的,我们可以通过event事件对象的各种属性来获得事件发生的坐标位置。
  常见的鼠标事件有下面这几种:

1. onclick
  鼠标点击事件

  let el = document.querySelector('#element-id');
  el.onclick = function(e){
      console.log(e)
  }

2. onmousedown
  鼠标按下事件

  let el = document.querySelector('#element-id');
  el.onmousedown = function(e){
      console.log(e)
  }

3. onmouseup
  鼠标松开事件

  let el = document.querySelector('#element-id');
  el.onmouseup = function(e){
      console.log(e)
  }

4. onmousemove
  鼠标移动事件

  let el = document.querySelector('#element-id');
  el.onmousemove = function(e){
      console.log(e)
  }

5. onmouseover
  鼠标经过事件

  let el = document.querySelector('#element-id');
  el.onmouseover = function(e){
      console.log(e)
  }

6. onmouseout
  鼠标划出事件

  let el = document.querySelector('#element-id');
  el.onmouseout = function(e){
      console.log(e)
  }

  根据以上打印的e的信息,大致为:
鼠标点击打印的MouseEvent信息

点击这里查看大图

  由鼠标事件(MouseEvent)可以发现:其中包含了许多的坐标,且每个坐标的含义都不一样。下面我们来挨个介绍常用的坐标,以及它们的含义。
  如图所示,假设页面中灰色圆点是鼠标点击处,棕色区域是鼠标触发事件对象。
图解鼠标事件坐标

点击这里查看大图

  结合前面的图,我们可以看到:e.x,e.y分别和e.clientX,e.clientY相等。

  事实上,e.layerX/e.layerY 与 e.x/e.y 这两个属性比较特殊考虑到它们不那么常见(因为受浏览器种类影响),而且使用时需要考虑的情况相对复杂(layerX/layerY对于absolute绝对定位元素,参考点是当前点击元素的左上角;对于relative相对定位元素,通常与pageX/pageY的值是相同的),这里不展开讨论(实用主义,感兴趣的可以单独拎出来尝试)。

三、不同浏览器对这些属性的支持

Chrome Firefox IE8 - IE9 IE10 +
offsetX ×
clientX
pageX ×
screenX
layerX ×
x ×

  上面列举的这些浏览器都在不断迭代版本,而且市面上还有很多其它浏览器,所以这部分内容需要实时参考MDN上的浏览器兼容性表格

四、总结

  上面那些属性都是很容易搞混的,常用的记在这里方便以后速查。一些特殊的属性尤其要注意不同的浏览器中可能存在的差别,使用的时候测试一下就能更准确的应用了。

  整理这篇文章的契机,就是我在编写cceditor这个项目的时候。

  如有异议,可以在留言区评论,或直接发送您宝贵的意见至我的邮箱。


参考
MDN
若干文章


  目录