JavaScript基础:元素在可视区域中

在这里插入图片描述

偏移量

偏移量概念公式
offsetHeight元素在垂直方向上占用的空间大小,以像素为单位。包括元素的高度、(可见的) 水平滚动条的高度、上下边框高度offsetHeght = content + padding + border + scrollX
offsetWidth元素在水平方向上占用的空间大小,以像素为单位。包括元素的宽度、(可见的)垂直滚动条的宽度、左右边框宽度offsetWidth = content + padding + border + scrollY
offsetLeft元素的左外边框距离与已定位的父容器(offsetParent)的左边距离(不包括元素的边框和父容器的边框)
offsetTop元素的上外边框距离与已定位的父容器的上边距离(不包括元素的边框和父容器的边框)

如下图:

在这里插入图片描述

小结:

  • 只读属性
  • 包括滚动条和边框,不包括外边距
  • 每次访问都要重新计算(用变量进行保存)

client 系列

客户区大小概念公式
clientWidthclientWidth 属性是元素内容区宽度加上左右内边距宽度,不包括滚动条、边框和外边距clientWidth = content + padding
clientHeight元素内容区高度加上上下内边距高度,不包括滚动条、边框和外边距clientHeight = content + padding
clientLeft实际上就是左边框宽度clientLeft = border-left
clientTop实际上就是上边框宽度clientLeft = border-top

常用于获取浏览器视口大小

function getViewport(){
    // 检查 document.compatMode 属性,以确定浏览器是否运行在混杂模式。
    // Safari3.1 之前的版本不支持这个属性,因此就会自动执行 else 语句
    if (document.compatMode == "BackCompat"){
        return {
            width: document.body.clientWidth,
            height: document.body.clientHeight
        };
    } else {
        return {
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        }; 
    }
}

小结:

  • 只读属性
  • 每次访问都要重新计算(用变量进行保存)

滚动 scroll 系列

滚动大小概念
scrollWidth在没有滚动条的情况下,元素内容的总高度
scrollHeight在没有滚动条的情况下,元素内容的总宽度
scrollLeft被隐藏在内容区域左侧的像素数。通过设置这个属性可以改变元素的滚动位置
scrollTop被隐藏在内容区域上方的像素数。通过设置这个属性可以改变元素的滚动位置
  • scrollWidthscrollHeight 主要用于确定元素内容的实际大小
  • scrollLeftscrollTop 属性既可以确定元素当前滚动的状态,也可以设置元素的滚动位置
    • 垂直滚动 scrollTop > 0
    • 水平滚动 scrollLeft > 0
  • 将元素的 scrollLeftscrollTop 设置为 0,可以重置元素的滚动位置

在这里插入图片描述

确定元素大小

Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,该对象提供有关元素大小及其相对于视口的位置的信息

这个方法返回一个矩形对象,含4个属性:lefttoprightbottom 。这些属性给出了元素在页面中相对于视口的位置

  • top:元素上边到视窗上边的距离
  • right:元素右边到视窗左边的距离
  • bottom:元素下边到视窗上边的距离
  • left:元素左边到视窗左边的距离

在这里插入图片描述

对于不支持 getBoundingClientRect() 的浏览器,可以通过其他手段取得相同的信息。一般来说,rightleft 的差值与 offsetWidth 的值相等,而 bottomtop 的差值与 offsetHeight 相等


function getElementLeft(element){
    let actualLeft = element.offsetLeft;
    let current = element.offsetParent;
    while (current !== null){
        actualLeft += current.offsetLeft;
        current = current.offsetParent;
    }
    return actualLeft;
}

function getElementTop(element){
    let actualTop = element.offsetTop;
    let current = element.offsetParent;
    while (current !== null){
        actualTop += current. offsetTop;
        current = current.offsetParent;
    }
    return actualTop;
}

function getBoundingClientRect(element) {
    //计算滚动条外的长度(用于去除)
    let scrollTop = document.documentElement.scrollTop;
    let scrollLeft = document.documentElement.scrollLeft;
    if (element.getBoundingClientRect) {
        //判断是否已经运行过此函数,如果已运行过,则会在arguments.callee.offset保存浏览器的数据,也就不再进入if语句块
        if (typeof arguments.callee.offset != "number") {
            //创建一个dom元素用于测量左上角的坐标是(0,0)还是(2,2)
            let temp = document.createElement("div");
            //必须绝对定位定位在左上角,不然会加到文档的末尾测量出现巨大偏差
            temp.style.cssText = "position:absolute;left:0;top:0;"; 
            document.body.appendChild(temp);
            //去除窗口外的距离,如果IE<=7则
            arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop; 
            document.body.removeChild(temp);
            temp = null;
        }
        let rect = element.getBoundingClientRect();
        let offset = arguments.callee.offset;
        return {
            left: rect.left + offset,
            right: rect.right + offset,
            top: rect.top + offset,
            bottom: rect.bottom + offset
        };
    } else {
        let actualLeft = getElementLeft(element);
        let actualTop = getElementTop(element);
        return {
            left: actualLeft - scrollLeft,
            right: actualLeft + element.offsetWidth - scrollLeft,
            top: actualTop - scrollTop,
            bottom: actualTop + element.offsetHeight - scrollTop
        }
    }
}

判断元素是否在可视区域

第一种方法

el.offsetTop - document.documentElement.scrollTop <= viewPortHeight

function isInViewPortOfOne (el) {
    // viewPortHeight 兼容所有浏览器写法
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
    const offsetTop = el.offsetTop
    const scrollTop = document.documentElement.scrollTop
    const top = offsetTop - scrollTop
    console.log('top', top)
     // 这里有个+100是为了提前加载+ 100
    return top <= viewPortHeight + 100
}

第二种方法

el.getBoundingClientReact().top <= viewPortHeight

function isInViewPortOfTwo (el) {
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
    const top = el.getBoundingClientRect() && el.getBoundingClientRect().top
    console.log('top', top)
    return top  <= viewPortHeight + 100
}

第三种方法

intersectionRatio > 0 && intersectionRatio <= 1

// 定义一个交叉观察器
const io = new IntersectionObserver(ioes => {
    ioes.forEach(ioe => {
        const el = ioe.target
        const intersectionRatio = ioe.intersectionRatio
        if (intersectionRatio > 0 && intersectionRatio <= 1) {
            loadImg(el)
            io.unobserve(el)
        }
         el.onload = el.onerror = () => io.unobserve(el)
    })
})
// 执行交叉观察器
function isInViewPortOfThree (el) {
    io.observe(el)
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值