鼠标事件都是在特定位置发生的,我们可以通过event事件对象的各种属性来获得事件发生的坐标位置,有相对于视口的,有相对于整个文档的,同样页面元素的位置也有相对视口的,也有滚动后的,这些都比较容易混淆,所以整理在这里,备忘,待查。
1.客户区坐标位置(clientX/clientY)
我们可以通过event事件对象的clientX/clientY属性获得事件发生时鼠标指针在视口中的水平和垂直坐标。
示意图:
2.屏幕坐标位置(screenX/scrennY)
通过event事件对象的screenX/screenY属性,可以获取鼠标事件发生时鼠标光标相对于整个电脑屏幕的坐标信息。
示意图:
clientX/clientY和screenX/screenY区别demo:clientX/clientY和screenX/screenY区别demo
demo 源代码戳这里:https://github.com/demo.html
3.页面坐标位置(pageX/pageY)
通过事件对象的pageX/pageY属性可以获得鼠标事件发生时鼠标光标相对于整个文档元素的坐标位置(包含滚动)。
在页面没有滚动的情况下,通常pageX/pageY的值与clientX/clientY的值相等。
4.layerX/layerY
事件对象还有个不那么常见的属性,那就是layerX/layerY,他是对于绝对定位元素来说的,相对于当前点击元素的左上角定位的。当页面上的元素时相对定位(position:relative)的时候,通常pageX/pageY和layerX/layerY的值是相同的,但是当元素绝对定位(position:absolute)了的时候,layerX/layerY就将鼠标光标位置相对于本身的左上角定位了。
下面demo有助于理解,猛戳:
pageX\pageY & layerX\layerY示意demo:pageX\pageY & layerX\layerY
demo代码猛戳这里:https://github.com/pageXandLayerX.html
5.偏移量:(offsetWidth/offsetHeight/offsetLeft/offsetTop)
元素的偏移量(offsetLeft/offsetTop)是相对于它的直接父元素来说的。
[元素的可见大小由其高度和宽度决定,这包括所有的内边距(padding)、滚动条和边框(border)大小(注意这里面不包括margin喔,因为margin是透明的,一般使用它控制元素之间的间隔)。这是为什么呢,因为吧,可以一试,如果我们给元素添加背景的话,那么背景会被应用 于由内容和内边距组成的区域,而添加边框(border)会在内边距(padding)的区域外边加一条线,margin透明,当然不在可见范围内啦。]
示意图:
Tips:
1.如果要想知道某个元素在页面上的偏移量,将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,如此循环至根元素,就可以得到一个基本准确的值。
2.如果有些div他的offsetParent是<body>的话,那么也可以尝试getElementLeft()和getElementTop()方法,不出意外地话会返回跟offsetLeft和offsetTop相同的值。
3.所有这些偏移量都是只读的,而且每次访问的时候都需要重新计算,要注意性能问题。
6.客户区的大小(clientWidth/clientHeight)
元素的客户区的大小就是指元素内容及其内边距所占空间的大小(滚动条占用的空间不计算在内)。(clientWidth=width+padding(left、right);clientHeight=height+padding(top、bottom))
clientWidth与offsetWidth区别示例:clientWidth与offsetWidth区别
7.滚动大小(scrollWidth/scrollHeight/scrollLeft/scrollTop)
有些元素,即使没有执行任何代码也会自动的添加滚动条,如<html>,但是另外一些元素,则需要通过css的overflow属性进行设置才能滚动。
通常认为<html>元素是在web浏览器的视口中滚动的元素(ie6之前版本运行在混杂模式下是<body>元素,这也是上面计算视口大小代码if,else的原因),因此带有垂直滚动条的页面总高度就是document.documentElement.scrollHeight。
当overflow属性设置为 auto时,内容可以超过元素的尺寸,并显示滚动条。这时就可以使用scrollwidth属性来检索内容的宽度范围内的元素。
MSDN上找到了相关的例子:scrollWidth属性示例
更具体的信息,可以查看这里:MSDN scrollWidth
Tips:
在确定文档的总高度时,必须取得scrollWidth、clientWidth和scrollHeight、clientHeight中的最大值,这样才能保证在跨浏览器的情况下取得较为准确的结果。
8.window.scrollX/window.scrollY与window.pageXOffset/window.pageYOffset
window.scrollX/window.scrollY返回的是整个文档document在水平和竖直方向滚动了的距离。
window.pageXOffset/window.pageYOffset相当于window.scrollX/window.scrollY的别名一样的。也就是说:
window.pageXOffset == window.scrollX; // 总是返回真
但在跨浏览器的情况下,尽量使用window.pageXOffset/window.pageYOffset比较好。
所以为了保险起见,使用下面这样的代码来判断文档在垂直和水平防线滚动的距离比较好:
var x = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;
var y = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
9.window.innerHeight/window.innerWidth
window.innerHeight/window.innerWidth记录了视口内文档元素的实际高度和宽度,实际上还有window.outerHeight/window.outerWidth。
下图可以很好地区分两者:
另外,如果页面滚动了也不会影响他的innerHeight和innerWidth值:
此外,如果页面中有frameset时:
var intFrameHeight = window.innerHeight; // or var intFrameHeight = self.innerHeight;
// will return the height of the frame viewport within the frameset var intFramesetHeight = parent.innerHeight;
// will return the height of the viewport of the closest frameset var intOuterFramesetHeight = top.innerHeight;
// will return the height of the viewport of the outermost frameset
10.getBoundingClientRect()方法
getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。getBoundingClientRect是DOM元素到浏览器可视范围的距离(不包含文档卷起的部分)。该函数返回一个Object对象,该对象有6个属性:top,lef,right,bottom,width,height;这里的top、left和css中的理解很相似,width、height是元素自身的宽高,但是right,bottom和css中的理解有点不一样。right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。
通过这个方法可以比较方便的获取页面元素的位置:
var X= this.getBoundingClientRect().left+document.documentElement.scrollLeft;
var Y =this.getBoundingClientRect().top+document.documentElement.scrollTop;
关于这个方法MSDN上有详细的解释:getBoundingClientRect()方法
总结:
上面那些属性都是很容易搞混的。而且也要注意不同的浏览器中可能存在的差别,使用的时候测试一下就能更准确的应用了。
搞清楚了上面这些相关属性和方法,应该就能理解小胡子写给我的这个demo了:js原生拖放
源代码在这里:https://github.com/dragdemo.html
整理这篇文章的契机,就是我在实现原生的拖放功能。
备忘,待查。