[前端小项目] 滚动动画 Scroll Animation (50projects50days)

📰前言


👨‍🏫分析


布局

水平居中的实现较为简单,可以使用margin:0 auto;,也可以使用flex布局:

#container{
    display:flex;
    flex-direction:column;
    align-items:center;
}

绑定滚动事件

  • 滚动事件可以考虑节流,但是这里内容比较简单,就不使用节流了(主要是不会🙊),原项目的代码也没有用节流。
  • 滚动事件可以用事件监听addEventListener()绑定到window对象上(也可以就绑定到document上)。
  • 触发滚动事件后,执行对应的函数——判断哪些卡片是显示的,哪些是不显示的(在窗口外部的)。

判断是否显示卡片

  • 获取卡片元素,使用querySelectorAll(),得到一个静态的NodeList(伪数组)。
  • 使用forEach()方法,对每一个卡片判断是否显示。
  • 显示原则:当卡片的顶部到达视图窗口的顶部的距离小于视图窗口的高度时,说明卡片到达视图窗口了,便可以显示出来。
  • 此处用到了getBoundingClientRect()方法和Window.innerHeight属性,后者返回视图窗口的高度。
  • 关于getBoundingClientRect()MDN Web Docs是这样解释的:

Element.getBoundingClientRect()方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
语法
getBoundingClientRect()
参数
无。
返回值
返回值是一个 DOMRect 对象,是包含整个元素的最小矩形(包括 padding 和 border-width)。该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。

  • 在原GitHub项目给出的代码中,其判断条件是卡片使用getBoundingClientRect()方法后,获取top值,然后再和Window.innerHeight\(\frac{4}{5}\)做比较,此处的\(\frac{4}{5}\)应该是优化参数,影响不大。

👩‍💻代码实现

Html

点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>scroll-animation</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <!-- 提示语句 -->
    <h1>Scroll to See the Animation</h1>

    <!-- 卡片列表 -->
    <div id="list">
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
        <div class="box">
            <p>content</p>
        </div>
    </div>
</body>
<script src="script.js"></script>
</html>

Css

点击查看代码
*{
    box-sizing: border-box;
}

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

#list{
    /* 卡片居中排列 */
    display: flex;
    flex-direction: column;
    align-items: center;
}

#list .box{
    /* 卡片通用样式 */
    width: 320px;
    height: 200px;
    background-color:#4682b4;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 1rem;
    box-shadow: 2px 4px 5px rgb(0 0 0 / 30%);
    margin: 10px 0;
    transition: transform ease 0.4s;
}

/* 偶数盒子不显示时,向右边偏移 */
#list .box:nth-of-type(2n){
    transform: translateX(400%);
}

/* 奇数盒子不显示时,向左边偏移 */
#list .box:nth-of-type(2n+1){
    transform: translateX(-400%);
}

#list .box p{
    color: #fff;
    font-size: 32px;
    font-weight: bold;
}

/* 添加上.show类的盒子取消平移量,回到中间 */
#list .box.show{
    transform: translateX(0%);
}

JavaScript

点击查看代码
window.onload = function(){
    //获取盒子元素
    const boxes = document.querySelectorAll('.box');

    //判断所有盒子中,有哪些盒子是要显示出来的
    function check(){
        //forEach()方法是一种数组迭代方法
        boxes.forEach(box=>{
            //对每一个卡片判断是否显示出来
            //这里使用了getBoundingClientRect()方法和window.innerHeight属性
            if(box.getBoundingClientRect().top <= window.innerHeight*4/5){
                box.classList.add('show');
            }else{
                box.classList.remove('show');
            }
        });
    }

    //绑定滚动事件
    document.addEventListener('scroll',check);
    //页面加载完,先判断当前视口内有哪些卡片是要显示的
    check();
    
}

📝知识点清单

  1. 数组迭代方法:forEach()
  2. 获取当前卡片在窗口的相对位置时,可以使用getBoundingClientRect()方法和window.innerHeight属性进行计算、判断。
  3. 使用Css选择器的过程中,要注意空格的存在,比如.box .show(中间有空格)表示带有.box的元素的子元素中带有.show的元素;而.box.show(中间无空格)则选择到了同时带有.box.show这两个类的元素。

📚参考文章

[1]Element.getBoundingClientRect()
[2]Window.innerHeight
[3]CSS选择器参考手册

posted @ 2022-06-29 22:19  feixianxing  阅读(101)  评论(0编辑  收藏  举报