在Javascript的开发过程当中,咱们总会看到相似以下的边界条件判断(懒加载):git
const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight; const innerHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight if( scrollTop +innerHeight >= scrollHeight + 50) { console.log('滚动到底了!') }
这些获取滚动状态的属性,可能咱们咋一看可以理解,不过期间久了立马又忘记了。这是由于这些获取各类宽高的属性api及其的多,并且几乎都存在兼容性写法。一方面很难记,更重要的是很差理解。下面经过选取经常使用的几个来说述下具体api的区别。github
## 一 挂在window上的api
window上最经常使用的只有window.innerWidth/window.innerHeight、window.pageXOffset/window.pageYOffset.浏览器
其中,window.innerWidth/windw.innerHeight永远都是窗口的大小,跟随窗口变化而变化。window.pageXOffset/window.pageYOffset是IE9+浏览器获取滚动距离的,实质跟document.documentElement/document.body上的scrollTop/scrollLeft功能一致,因此平常都使用兼容写法:spa
const scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
pageYOffset 属性实质是 window.scrollY 属性的别名,pageXOffset同理,为了跨浏览器兼容,通常用后者(pageYOffset、pageXOffset)。
记住公式:3d
clientWidth/clientHeight = padding + content宽高 - scrollbar宽高(若有滚动条)
我的以为这个名字有点误导人,压根没有偏移的意思,记住公式便可:code
offsetWidth/offsetHeight = clientWidth/clientHeight(padding + content) + border + scrollbar
由上述公式,能够获得第一个示例,即"获取滚动条的宽度(scrollbar)":blog
const el = document.querySelect('.box') const style = getComputedStyle(el, flase)//获取样式 const clientWidth = el.clientWidth, offsetWidth = el.offsetWidth //parseFloat('10px', 10) => 10 const borderWidth = parseFloat(style.borderLeftWidth, 10) + parseFloat(style.borderRightWidth, 10) const scrollbarW = offsetWidth - clientWidth - borderWidth
这两个才是真的意如其名,指的是元素上侧或者左侧偏移它的offsetParent的距离。这个offsetParent是距该元素最近的position不为static的祖先元素,若是没有则指向body元素。说白了就是:"元素div往外找到最近的position不为static的元素,而后该div的边界到它的距离"。
由此,能够获得第二个示例,即"得到任一元素在页面中的位置":事件
const getPosition = (el) => { let left = 0, top = 0; while(el.offsetParent) { //获取偏移父元素的样式,在计算偏移的时候须要加上它的border const pStyle = getComputedStyle(el.offsetParent, false); left += el.offsetLeft + parseFloat(pStyle.borderLeftWidth, 10); top += el.offsetTop + parseFloat(pStyle.borderTopWidth, 10); el = el.offsetParent; } return { left, top } }
那么,offsetLeft和style.left有什么区别呢?ip
因此,通常通用用法是:“用offsetLeft 和 offsetTop 获取值,用style.left 和 style.top 赋值”
综上,结合getBoundingClientRect()获得综合示例"元素是否在可视区域":
function isElemInViewport(el) { const rt = el.getBoundingClientRect(); return ( rt.top >=0 && rt.left >= 0 && rt.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rt.right <= (window.innerWidth || document.documentElement.clientWidth) ) }
其中,getBoundingClientRect用于得到页面中某个元素的左,上,右和下分别相对浏览器视窗的位置:
event上面的相对距离通常是鼠标点击或者移动端触控事件获取的。
鼠标或者触控点相对于可视窗口左上角为原点x轴和y轴的距离:
鼠标或者触控点相对于元素自己宽高左上角为原点x轴和y轴的距离:
鼠标或者触控点相对于屏幕显示器左上角为原点x轴和y轴的距离:
鼠标或者触控点相对于页面内容左上角为原点x轴和y轴的距离:
须要注意的是,这两个属性存在兼容性问题:
pageX = event.pageX || event.x; //IE pageY = event.pageY || event.y; //IE
本文收录在我的的Github上 https://github.com/kekobin/bl... ,以为有帮助的,欢迎start哈。支持原创,未经本人赞成,请勿转载!