标签归档:offset

DOM- 网页特效

1. 滚动事件和加载事件

1. 滚动事件scroll

  1. 当页面进行滚动时触发的事件

  2. 很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部

  3. 监听整个页面滚动给 window 或 document 加

  4. 监听某个元素的内部滚动直接给某个元素加即可

// 监听整个页面滚动
// 1. 滚动事件 监听整个页面滚动 固定导航/返回顶部
window.addEventListener('scroll', function () {
console.log(1)
})
let num1 = document.querySelector('.box')
num1.addEventListener('scroll', function () {
console.log(2)
})

2. 加载事件load

  1. 加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件

  2. 有些时候需要等页面资源全部处理完了做一些事情

  3. 老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到

  4. 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件

监听页面所有资源加载完毕:

// 监听整个页面资源给 window 加
// 2. 加载事件 监听页面资源加载完毕才执行load事件
// 也可以针对别的资源绑定load事件
// 把js写在head上面 导致dom元素找不到 用load事件
let n1 = document.querySelector('.box')
window.addEventListener('load', function () {
    console.log(11)
})
​

3. 加载事件DOMContentLoaded

  1. 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表 、图像等完全加载

监听页面DOM加载完毕:

// 给 document 添加 DOMContentLoaded 事件
// 2. 加载事件 等HTML文档加载完后再加载 无需等样式 图片就可以加载
document.addEventListener('DOMContentLoaded', function () {
    console.log(3)
})
​

2. scroll家族

  1. 我们想要页面滚动一段距离,比如100px,就让某些元素显示隐藏, 就可以使用scroll 来检测页面滚动的距离~

  2. 获取宽高: 获取元素的内容总宽高(不包含滚动条)返回值不带单位

  3. scrollWidth和scrollHeight

获取位置:

  1. 获取元素内容往左、往上滚出去看不到的距离

  2. scrollLeft和scrollTop

  3. 这两个属性是可以修改的

// 1. scroll家族 (了解)
let num1 = document.querySelector('.box')
// 当前宽度 不包含滚动条
console.log(num1.scrollWidth)
// 内容高度
console.log(num1.scrollHeight)
​
// 2. 被卷去的头部和左侧
num1.addEventListener('scroll', function () {
    console.log(this.scrollTop)
})
​
开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素
  1. document.documentElement HTML 文档返回对象为HTML元素

// 3. 检测页面滚动的距离
window.addEventListener('scroll', function () {
    // 返回HTML元素距离
    console.log(document.documentElement.scrollTop)
    // 可以给值/修改 但不要带单位
    document.documentElement.scrollTop = 200
})
​
  1. 被卷去的头部或者左侧用那个属性?是否可以读取和修改?

  1. 可以读取,也可以修改(赋值)

页面滚动显示返回顶部按钮
//需求:当页面滚动500像素,就显示返回顶部按钮,否则隐藏, 同时点击按钮,则返回顶部
//①:用到页面滚动事件
//②:检测页面滚动大于等于100像素,则显示按钮
//③:点击按钮,则让页面的scrollTop 重置为 0
<div class="content"></div>
<div class="backtop">
    <img src="./images/close2.png" alt="">
    <a href="javascript:;"></a>
</div>
let btn = document.querySelector('.backtop')
// 1. 页面滚动事件
window.addEventListener('scroll', function () {
    // 2. 页面检测滚动距离
    let num1 = document.documentElement.scrollTop
    // 3. 判断显示隐藏
    // 如果大于200 就显示 小于隐藏
    if (num1 >= 200) {
        btn.style.display = 'block'
    } else {
        btn.style.display = 'none'
    }
})
​
// 4. 点击链接返回顶部
btn.children[1].addEventListener('click', function () {
    document.documentElement.scrollTop = 0
})
​

3. offset家族

  1. 使用场景: 前面案例滚动多少距离,都是我们自己算的,最好是页面 滚动到某个元素,就可以做某些事

  2. 简单说,就是通过js的方式,得到元素在页面中的位置 这样我们可以做,页面滚动到这个位置,就可以返回 顶部的小盒子显示…

获取宽高:
  1. 获取元素的自身宽高、包含元素自身设置的宽高、padding、border, offsetWidth和offsetHeight

// 1. offset家族 宽高 (了解)
let num1 = document.querySelector('.box')
// 盒子大小 = 盒子本身宽高 + padding + border
// 盒子多大 offset就多大
console.log(num1.offsetWidth)
console.log(num1.offsetHeight)
​
获取位置:
  1. 获取元素距离自己定位父级元素的左、上距离

  2. offsetLeft和offsetTop 注意是只读属性

// 2. 位置以带定位的父级 如果没有就以左上角为准
console.log(num1.offsetTop)
console.log(num1.offsetLeft)
​
仿京东固定导航栏案例
//当页面滚动到秒杀模块,导航栏自动滑入,否则滑出
//①:用到页面滚动事件
//②:检测页面滚动大于等于 秒杀模块的位置 则滑入,否则滑出
<div class="header">我是顶部导航栏</div>
<div class="content">
    <div class="sk">秒杀模块</div>
</div>
<div class="backtop">
    <img src="./images/close2.png" alt="">
    <a href="javascript:;"></a>
</div>
<script>
let box = document.querySelector('.sk')
let head = document.querySelector('.header')
// 1.页面滚动事件
window.addEventListener('scroll', function () {
// 2.检测页面滚动距离 >= 秒杀模块的offsetTop 则划入
    if (document.documentElement.scrollTop >= box.offsetTop) {
// 3.如果大于则显示 小于则-80px
        head.style.top = '0px'
    } else {
        head.style.top = '-80px'
    }
})
</script>
电梯导航案例
<!--需求:点击可以页面调到指定效果
①:点击当前 小导航,当前添加active,其余移除active
②:得到对应 内容 的 offsetTop值
③:让页面的 scrollTop 走到 对应 内容 的 offsetTop-->
<div class="aside">
    <div class="item active">男装/女装</div>
    <div class="item">儿童服装/游乐园</div>
    <div class="item">电子产品</div>
    <div class="item">电影/美食</div>
</div>
<div class="content">
    <div class="neirong content1">男装/女装</div>
    <div class="neirong content2">儿童服装/游乐园</div>
    <div class="neirong content3">电子产品</div>
    <div class="neirong content4">电影/美食</div>
</div>
<script>
let btn = document.querySelectorAll('.item')
let btn1 = document.querySelectorAll('.neirong')
// 1. 点击谁谁添加类
for (let num1 = 0; num1 < btn.length; num1++) {
    btn[num1].addEventListener('click', function () {
        document.querySelector('.aside .active').classList.remove('active')
        this.classList.add('active')
        // 2. 右侧内容跟随走动
        // 让页面滚动对应offsettop值位置
        document.documentElement.scrollTop = btn1[num1].offsetTop
    })
}
</script>

4. client家族

  1. 获取宽高:获取元素的可见部分宽高(不包含边框,滚动条等), clientWidth和clientHeight

  2. 获取位置: 获取左边框和上边框宽度, clientLeft和clientTop 注意是只读属性

let num1 = document.querySelector('.box')
// 可见区域的宽高 不包含滚动条 边框...
console.log(num1.clientWidth)
console.log(num1.clientHeight)
// 3. client TOP/Left (了解) 就是边框的宽高
console.log(num1.clientTop)
console.log(num1.clientLeft)
​
会在窗口尺寸改变的时候触发事件:resize
// 2. resize事件 当窗口变化时触发的事件
window.addEventListener('resize', function () {
    // 检测屏幕宽度
    console.log(document.documentElement.clientWidth)
    // 检测页面的宽度不同而改变颜色
    let num2 = document.documentElement.clientWidth
    if (num2 >= 1000) {
        document.body.style.backgroundColor = 'skyblue'
    } else if (num2 >= 850) {
        document.body.style.backgroundColor = 'pink'
    } else {
        document.body.style.backgroundColor = 'green'
    }
})
​

5. 三大家族的区别

offset家族

  1. 获取元素自身大小:包括自身设置的宽高、padding、border

  1. 获取元素距离定位父级的左和上距离 只读属性

scroll家族

  1. 获取元素内容的总大小

  1. 获取元素向左向上滚出去看不见的距离 可读写属性

client家族

  1. 获取元素可见区域的大小

  1. 获取元素左、上边框距离 只读属性 

6. 轮播图案例

需求①:小图标鼠标经过事件

需求② :大图片跟随变化

需求③:右侧按钮播放效果

需求④:解决一个BUG

需求⑤:左侧按钮播放效果

需求⑥: 因为左侧按钮和右侧按钮里面有大量相同的操作,可以抽取封装一个函数 common

需求⑦:开启定时器需求

需求⑧: 鼠标经过停止定时器 (清除定时器) 鼠标离开开启定时器 (开启定时器) 

<div class="main">
    <div class="slides">
        <ul>
            <li class="active"><a href="#"><img src="./images/b_01.jpg" alt="第1张图的描述信息"></a></li>
            <li><a href="#"><img src="./images/b_02.jpg" alt="第2张图的描述信息"></a></li>
        </ul>
        <div class="extra">
            <h3>第1张图的描述信息</h3>
            <a class="prev" href="javascript:;"></a>
            <a class="next" href="javascript:;"></a>
        </div>
    </div>
    <div class="indicator">
        <ul>
            <li class="active">
                <img src="images/s_01.jpg">
                <span class="mask"></span>
                <span class="border"></span>
            </li>
            <li>
                <img src="images/s_02.jpg">
                <span class="mask"></span>
                <span class="border"></span>
            </li>
        </ul>
    </div>
</div>
let xl = document.querySelectorAll('.indicator li')
let dl = document.querySelectorAll('.slides ul li')
let text = document.querySelector('.extra h3')
let btn = document.querySelector('.next')
let btn1 = document.querySelector('.prev')
let main = document.querySelector('.main')
for (let num1 = 0; num1 < xl.length; num1++) {
    // 1.鼠标经过小图片变高亮
    xl[num1].addEventListener('mouseenter', function () {
        document.querySelector('.indicator .active').classList.remove('active')
        this.classList.add('active')
    // 2. 鼠标经过当前小图片后大图片变化
    // 利用opacity实现淡入淡出效果
        document.querySelector('.slides .active').classList.remove('active')
        dl[num1].classList.add('active')
    // 3. 鼠标经过图片 文字改变
        text.innerHTML = `第${num1 + 1}张图的描述信息`
​
    // 6. 解决Bug 如果鼠标经过后 再次点击播放会乱序
    // 让index重新赋值为 当前鼠标经过索引号
        index = num1
    })
}
​
// 4. 右侧按钮点击事件
// 全局变化量变量 不断自增 控制器/给左右按钮同时使用
let index = 0
btn.addEventListener('click', function () {
    index++  // 变量点击后自增
​
    // 1. 解决点击最后一张后报错 等于10之后index为0
    if (index == 10) {
        index = 0
    }
    // 2. // 10 10 余 0
    // index = index % 10 
    fn()
})
​
// 5.左侧按钮点击事件
btn1.addEventListener('click', function () {
    index--
    if (index < 0) {
        index = 9
    }
    // 10 + -1 = 9 % 10 余 1
    // index = (10 + index) % xl.length
    fn()
})
​
// 6. 因为左右按钮有大量相同代码 可以封装成函数 然后调用
function fn() {
    // 选出 index 大/小图片 排它思想
    document.querySelector('.indicator .active').classList.remove('active')
    xl[index].classList.add('active')
    document.querySelector('.slides .active').classList.remove('active')
    dl[index].classList.add('active')
    text.innerHTML = `第${index + 1}张图的描述信息`
}
​
// 7. 开启轮播定时器
let timer = setInterval(function () {
// 自动调用右侧按钮点击事件
    btn.click()
}, 800)
​
// 如果不清除 点击哪个就不会停止
// 8.鼠标经过清除定时器
main.addEventListener('mouseenter', function () {
    clearInterval(timer)
})
​
// 9. 鼠标经过开启定时器
main.addEventListener('mouseleave', function () {
// 直接再开启一个定时器 不要重新赋值了
    timer = setInterval(function () {
        btn.click()
    }, 800)
})
​