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