50 Projects 50 Days - Scroll Animation 学习记录

项目地址

Scroll Animation

展示效果

50 Projects 50 Days - Scroll Animation 学习记录_第1张图片
Scroll Animation

实现思路

HTML结构比较简单,就是10+个盒子元素。当鼠标滚动时,盒子分别从左右移动过来。
思路上最开始想到的是给每一个盒子标记一个序号,滚动屏幕后,计算已经划动屏幕的距离和盒子高度的比例,得到应该移动回来的最后一个序号。这种思路当然也可以实现,但是不是最简便的方式,计算上也比较容易出现边界情况。
案例给出的方法比较简便,只需要通过Web API获取每个元素距离屏幕顶部的距离,当这个距离小于某个阈值时就移动回来,这样的好处时每个元素只需要关心自己的距离就行,不会像计算思路那样与整个内容区域强制绑定在一起,真正实现了解耦。

实现细节

HTML结构

只需要列出10+个盒子模型即可。也可以在JavaScript里循环添加这个元素。

<body>
    <h1>Scroll to see the animationh1>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <div class="box"><h2>Contenth2>div>
    <script src="script.js">script>
  body>

CSS样式

默认样式transform水平移动一个距离,能够做到不在可视区域内即可;为了达到左右交替移动的效果,双数位的盒子可以设置为反方向移动。等到了满足条件时,再添加一个show的class,覆盖原有的transform。
4倍的盒子宽度已经能够移出常规屏幕的可视区域了,因此这里移动是400%。

.box {
  background-color: steelblue;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 400px;
  height: 200px;
  margin: 10px;
  border-radius: 10px;
  box-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3);
  transform: translateX(400%);
  transition: transform 0.4s ease;
}

.box:nth-of-type(even) {
  transform: translateX(-400%);
}

.box.show {
  transform: translateX(0);
}

JavaScript逻辑

只需要一个函数即可,调取API的getBoundingClientRect().top得到每个盒子距离顶部的距离,当小于4/5的可视高度时,就添加show的class即可。
50 Projects 50 Days - Scroll Animation 学习记录_第2张图片

然后window滚动事件绑定该函数。
另外第一次加载也需要调用一次,因为此时并没有触发滚动事件,那么所有盒子都不会显示。

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

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. 使用Web API的getBoundingClientRect()方法获取元素相对于viewport的位置信息
  2. 对每个盒子单独进行条件判断和添加class,实现逻辑的解耦

你可能感兴趣的:(学习,css,javascript,前端,html)