鼠标事件和距离属性

js中有不少“距离”,为了避免会混淆这里总结一下其中部分距离chrome

本文包括元素属性相关的距离和鼠标事件中的距离,废话很少说,进入正文编程

先补充一下,本文的测试环境以下:windows

Chrome Dev 54.0.2840.71
Firefox 49.0
Opera 41.0
Safari 10.1
IE 11。

前四者运行在macOS Sierra 10.12上,IE11运行在搭载windows10 1607的虚拟机上浏览器

元素属性中的各类“距离”

元素属性中的距离有如下6对:测试

scrollLeft: 设置或获取位于对象左边界和窗口中可见内容的最左端之间的距离
scrollTop: 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离

offsetHeight: 得到对象的可视区域的高度,包括边框
offsetWidth: 得到对象的可视区域的宽度,包括边框spa

clientHeight: 得到对象边框内部分的高度
clientWidth: 得到对象边框内部分的宽度firefox

offsetLeft: 获取对象相对于版面或由offsetParent属性指定的父坐标的计算左侧位置
offsetTop: 获取对象相对于版面或由offsetTop属性指定的父坐标的计算顶端位置3d

clientTop: 获取对象顶部边框宽度
clientLeft: 获取对象左侧边框宽度code

scrollWidth: 获取对象的滚动宽度
scrollHeight: 获取对象的滚动高度。orm

上面提到了offsetParent属性,其实当前div相对谁定位,这个属性就是谁。根据position值不一样,有如下2种状况

  • 当父辈元素都没有relative属性时,不管当前元素的position是absolute,relative,fixed或fixed,offsetParent都是body元素
  • 父辈元素有relative属性时,不管当前元素的position是absolute,relative,fixed或fixed,offsetParent是具备relative属性的最近父元素

分不清楚? 看下图

这个里面能够清晰的看到上方的前4对,和他们之间的关系。

关于jQuery的元素距离属性,文章最后整理了他们和DOM属性之间的关系。

第一个值得强调的是,上面的这个例子中的div的box-sizing属性是默认的content-box, 它的offsetHeight,clientHeight,clientWidth和offsetWidth有以下关系:

clientHeight = height + paddingTopWidth + paddingBottomWidth;
clientWidth = width + paddingLeftWidth + paddingRightWidth;

offsetHeight = clientHeight + borderTopWidth + borderBottomWidth;
offsetWidth = clientWidth + borderLeftWidth + borderRightWidth;

若是box-sizing属性是border-box,那么,它们的关系将以下(ie6 ie7默认是这样的):

offsetHeight = height;
offsetWidth = width;

clientHeight = height - borderTopWidth - borderBottomWidth;
clientWidth = width - borderLeftWidth - borderRightWidth;

第二个值得强调的是,这个例子中,因为它的父元素没有设置position:relative,因此图中这个div利用position:absolute;相对文档定位,若是给他添加一个具备position:relative属性的父div,那么offsetLeft和offsetTop就是下图这样:

不过不管它怎么的定位,哪怕是position:relative或fixed,它的计算关系也不会发生变化,依然是:

offsetLeft = left + marginLeft;
offsetTop = top + marginTop;

讲了这么多,那么scrollWidth和scrollHeight呢?scrollWidth和scrollHeight在不一样浏览器里面并不一致,以下图(从左到右依次是Chrome, Firefox, Opera, Safari, IE11)

diff

其实仔细研究这个里面的不一样,会发如今不一样的浏览器div的offsetLeft、offsetTop这两个值的属性并不彻底相同。当div里面的内容溢出时,只有IE保留了padding的所有值,chrome、opera和safari会忽略padding-right的值视其为0,firefox会同时忽略padding-right和padding-bottom,以下图

在各个浏览器中,对于滚动条自己的渲染也不同。它们会在计算scrollWidth和scrollHeight时排除各自的滚动条宽度。除了上述的不一样,实际发现每一个浏览器中scrollLeft和scrollTop的最大值也不同,甚至差距极大,因为scrollLeft和scrollTop随滚动事件发生而输出,博主就上述例子的最大值记录以下:

maximum value chrome Firefox opera safari IE11
scrollLeft 330 160 827 330 217
scrollTop 230 210 485 230 330

实际上就是因为这些元素属性在不一样浏览器中的差别致使scrollWidth和scrollHeight的不一样,具体使用应格外注意。不过博主看过一些资料表示这两个属性和offsetParent有关,经过实际编程发现它们和offsetParent无关,这里不展开描述了,由于低版本浏览器,尤为ie7 ie6的实现方式可能会比较奇葩。

鼠标事件中的各类“距离”

鼠标事件不少,不过每一个事件中关于距离的属性含义是同样的,这里用mousemove来说解,具体的内容会在不久以后写到了js事件部分讲解。
鼠标实现对于如今的浏览器来讲,实现都是同样的了,下面例子都在Chorme中实现。

鼠标事件有如下6对:

event.clientX:相对浏览器左上角的水平坐标
event.clientY:相对浏览器左上角的垂直坐标

event.offsetX:相对于事件源(event.target||event.srcElement)左上角水平偏移
event.offsetY:相对于事件源(event.target||event.srcElement)左上角垂直偏移

event.pageX:相对于document左上角的水平坐标
event.pageY:相对于document左上角的垂直坐标

event.layerX:相对于offsetParent左上角的水平偏移
event.layerY:相对于offsetParent左上角的水平偏移

event.movementX:相对于前一次事件中screenX的偏移
event.movementY:相对于前一次事件中screenY的偏移

event.screenX:相对于屏幕左上角的水平坐标
event.screenY:相对于屏幕左上角的垂直坐标

x:和pageX同样,用于兼容IE8及之前浏览器
y:和pageY同样,用于兼容IE8及之前浏览器

总之,仍是先看图

<todo>
*这个图中,黑色实线边框表示浏览器可视区域部分,外层蓝色虚线框表示整个DOM部分,整个图为电脑屏幕

图里面怎么没有movementX和movementY?由于这个事件的值和上一个事件有关,关系以下:

currentEvent.movementX = currentEvent.screenX - previousEvent.screenX
currentEvent.movementY = currentEvent.screenY - previousEvent.screenY

值得注意的时offsetX和offsetY,他表示鼠标到事件源padding左上角的的偏移,这里mousemove事件注册在window上,因此位置如图所示。

当浏览器的水平滚动条滑动之后,pageX和clientX就不一样了。同理,当浏览器的垂直滚动条滑动之后,pageY和clientY就不一样了,但它们始终存在如下关系:

event.pageX = event.clientX + body.scrollLeft;
event.pageY = event.clientY + body.scrollTop;

鼠标事件中的距离比元素中的简单一些,具体的使用放在以后写的事件部分。

jQuery中元素距离属性

var $div = $("#div");

$div.width(); //元素宽度,不包括padding和border
$div.height(); //元素高度,不包括padding和border

$div.innerWidth(); //元素内宽度,包括padding,不包括border
$div.innerHeight(); //元素内高度,包括padding,不包括border

$div.outterWidth(); //元素可见宽度,包括padding和border
$div.outterHeight(); //元素可见高度,包括padding和border

$div.outterWidth(true); //元素所有宽度,包括padding、border和margin$div.outterHeight(true); //元素所有高度,包括padding、border和margin