DAY6-滚动动画

前言

这个项目来源于GitHub上的一个开源项目https://github.com/bradtraversy/50projects50days,总共有50个用来练手的前端项目,我学习然后复现效果,并记录学习笔记和心得。

效果展示

scroll-animation (点击查看)

HTML&CSS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>scroll-animation</title>
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
    <style>
        body,html{
            margin: 0;
            padding: 0;
        }

        body{
            background-color: #efedd6;
            display: flex;
            flex-direction: column;
            align-items: center;
            overflow-x: hidden;
        }

        header{
            font-size: 1.8rem;
            font-weight: bold;
            width: 400px;
            text-align: center;
        }

        .content{
            background-color: #4682b4;
            color: #fff;
            font-size: 2.5rem;
            font-weight: bold;
            height: 200px;
            width: 400px;
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin: 10px 0;
            box-shadow: 2px 5px 5px #b8b7a5;
            transition: transform .5s;
            transform: translateX(-10000px);
        }

        .content:nth-child(odd){
            transform: translateX(10000px);
        }

        .content.show{
            transform: translateX(0px);
        }

    </style>
</head>
<body>
    <header>Scroll to see the animation</header>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>
    <div class="content">Content</div>

</body>
</html>

JS

const boxes = document.querySelectorAll('.content')

window.addEventListener('scroll', checkBoxes)

checkBoxes()

function checkBoxes() {
    const triggerBottom = window.innerHeight / 5 * 4

    boxes.forEach(box => {
        const boxTop = box.getBoundingClientRect().top

        if(boxTop < triggerBottom) {
            box.classList.add('show')
        } else {
            box.classList.remove('show')
        }
    })
}

总结

  1. css样式基本上没有什么难点,需要注意的点是body在x轴需要overflow-x: hidden,然后利用选择器奇数位的元素移动方向不同

  2. js方面:上面贴出的代码是原作者的,写的真的很优雅,我没有看他的实现之前,我的想法是判断滚动条的滚动距离超过每个元素的高度(200px),然后就让下一个元素添加.show,如果向上滚动,就减少已经显示的元素,这样写判断比较多,而且还容易出现bug。下边是我的代码,引以为戒吧。

    let contentList = document.querySelectorAll('.content')
    let lastHeight = 0
    
    window.onload = function (){
        let clientHeight = document.documentElement.clientHeight
        let count = Math.floor(clientHeight/200)
        render(count)
    }
    
    document.body.onscroll = function () {
        let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        let diff = scrollTop - lastHeight
        if (Math.abs(diff) >=200){
            let subCount = diff > 0 ? Math.floor(Math.abs(diff)/200) : Math.floor(Math.abs(diff)/200) * -1
            lastHeight = scrollTop
            console.log(subCount,diff)
            render(subCount)
        }
    }
    
    function render(count){
        let showContentList = document.querySelectorAll('.content.show')
        if (count > 0){
            for (let i = 0; i < showContentList.length + count; i++) {
                if (!contentList[i].classList.contains('show')){
                    contentList[i].classList.add('show')
                }
            }
        }else {
            for (let i = (showContentList.length + count); i < showContentList.length; i++){
                showContentList[i].classList.remove('show')
            }
        }
    }
    
  3. 可以添加下面的代码,把显示元素的页面区域表示出来,就比较容易理解

    <div class="test" style="position: fixed;top: 0;left: 0;"></div>
    
    const triggerBottom = window.innerHeight / 5 * 4
    test.style.width = '100%';
    test.style.height = triggerBottom + 'px'
    test.style.backgroundColor = 'rgba(0,0,0,.5)'
    

    image-20221109154122755

    可以看到,只要元素的顶部,在灰色的蒙版区域内就显示即可。


DAY6-滚动动画
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/day6-scroll-animation
作者
卑微幻想家
发布于
2022-11-09
许可协议