细说滚动问题,附带获取各种距离,宽高的API

5,342 阅读3分钟

在写动画等操作的时候,滚动问题是我们常见的问题,

一. 对于页面级别的滚动,也就是整个document,如果它的高度小于屏幕的高度,那么滚动就不会发生,如果document的高度大于屏幕的高度,这个时候我们就可以滚动页面了,此时正在滚动的是document,window是作为包含着document的外壳,如果我们想获取滚动距离,那我们就有下面两种方式:

  1. window.scrollX
  2. document.documentElement.scrollTop

这两种方式获取到的滚动距离是一样,只是站的角度不同。

如果我们想给滚动事件绑定回调函数,我们也有两个选择

  1. document.onscroll = (e) => console.log(e.target)
  2. window.onscroll = (e) => console.log(e.target)

这两种方式没有区别,不过两种方式的e.target指向的都是document对象,可以把window上触发的scroll事件看作事件冒泡

如果我们想手动把页面滚动到某个位置,有两种方法

  1. window.scroll(x,y)/window.scrollTo(x,y)
  2. window.scrollBy(x,y)

第一种方法是直接滚动到某个坐标,绝对位移,scroll和scrollTo的作用等同,第二种方法是相对位移,相对之前位置的偏移

二. 对于某个元素内部的滚动,比如div之类的元素,如果我们给他加上样式,让高度是个固定值,同时添加 { overflow:auto } , 这个时候如果div的子元素的高度大于它本身固定的高度,那么就会在div内部出现滚动。

如果我们想监测这个div内部的滚动事件,可以给它添加监听函数: document.querySelector('#xxx').onscroll = () => console.log('success')

如果我们想获取它的滚动距离:document.querySelector('#xxx').scrollTop

在这里,浏览器有个比较特别的地方,如果给html元素添加 { height:100% } , 那么html的高度就不会被内部元素撑起,而是等于浏览器的高度,这里是正常的,我们继续,把样式改为 { height: 100%; overflow:auto } , 按照道理说,如果此时bady的高度大于html高度,那么应该在html里出现滚动条,但是我测试的是没有,好像overflow不存在一样,继续把样式改为 { height: 100%; overflow:hidden } , 这里又变正常了,页面无法滚动。如果给html和body都加上 { height: 100%; overflow:hidden } , body里会出现滚动条。但此时给body添加onscroll事件是无效的,同时如果window上绑定了scroll事件,那么也会失效

对于一个元素来说,它有自己的盒模型,包含magin,border,padding,width,同时就有几种不同的宽度:

  1. offsetWidth: 包含border,padding,width
  2. scrollWidth:包含padding,width
  3. clientWidth:如果元素宽度超出了屏幕宽度,那么我们就只能看到这个元素的一部分,被我们看到的这部分宽度就是元素的clientWidth,包含width,padding

例子:document.querySelector('#xxx').scrollWidth

元素的高度和宽度类似。

浏览器的可视区域也有一个宽高,有的时候我们希望页面可以自适应的铺满不同设备的屏幕,就可以把屏幕的宽高直接赋值给最外层的元素:

  1. window.innerWidth
  2. window.innerHeight

当点击事件发生时,我们可以通过一些属性获取坐标

  1. screenX/Y:原点是设备屏幕的左上角
  2. pageX/Y:原点是页面左上角
  3. clientX/Y:原点是可是区域左上角

document.body.onclick = e => console.log(e.clientX/Y)

如果我们想同时获取元素宽高和它相对于可视区域左上角的距离,可以用getBoundingClientRect()方法,具体说明可查看https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect

scrollLeft和scrollTop类似,方向不同而已,就不说拉。

上面的有些api可能会涉及到是否包含伪元素,伪类,滚动条的问题,由于情况比较少见,这里没有去分类,如果需要,可自行MDN

参考链接:

CSSOM视图模式(CSSOM View Module)相关整理 www.zhangxinxu.com/wordpress/2…