在网页交互开发中,滚动触发动画可以让页面内容随用户滚动操作动态展示,提升页面的趣味性和可读性。实现这类效果的核心是将scroll事件监听与CSS关键帧动画结合,通过JavaScript监听滚动位置,动态控制CSS动画的触发与执行。

核心原理说明
滚动触发动画的实现分为两个核心部分,一是通过scroll事件获取用户的滚动位置,判断目标元素是否进入可视区域;二是提前定义好CSS关键帧动画,当元素进入可视区域时,通过添加对应的动画类触发动画执行。
scroll事件监听
scroll事件会在页面滚动时持续触发,我们可以通过监听该事件获取当前的滚动距离,结合元素的偏移位置判断元素是否进入可视区域。为了避免scroll事件触发过于频繁导致性能问题,通常会搭配节流函数使用。
CSS关键帧动画
CSS关键帧动画通过@keyframes规则定义动画在不同阶段的状态,再通过animation属性将动画绑定到元素上。我们可以提前定义好动画效果,默认不触发,当条件满足时再添加动画相关的类。
实现步骤
1. 定义HTML结构
首先创建需要触发动画的目标元素,这里以一个简单的卡片元素为例:
<div class="container"> <div class="animate-card">我是滚动触发的动画卡片</div> <div class="animate-card">我是第二个动画卡片</div> <div class="animate-card">我是第三个动画卡片</div> </div>
2. 编写CSS关键帧动画
定义元素进入可视区域时的动画效果,这里实现一个从下方淡入并上移的动画:
/* 定义关键帧动画 */
@keyframes fadeInUp {
0% {
opacity: 0;
transform: translateY(50px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
/* 动画类,默认不添加 */
.animate-card {
width: 300px;
height: 200px;
margin: 100px auto;
background-color: #f0f0f0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
/* 初始状态隐藏 */
opacity: 0;
transform: translateY(50px);
}
/* 触发动画时添加的类 */
.animate-card.show {
animation: fadeInUp 0.6s ease forwards;
}
3. 编写scroll事件监听逻辑
通过JavaScript监听页面滚动,判断元素是否进入可视区域,进入时添加show类触发动画:
// 节流函数,避免scroll事件触发过于频繁
function throttle(fn, delay) {
let timer = null;
return function() {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
};
}
// 判断元素是否进入可视区域
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.bottom >= 0
);
}
// 处理滚动逻辑
function handleScroll() {
const animateCards = document.querySelectorAll('.animate-card');
animateCards.forEach(card => {
// 如果已经添加过show类,不再重复处理
if (card.classList.contains('show')) return;
if (isElementInViewport(card)) {
card.classList.add('show');
}
});
}
// 监听scroll事件,使用节流处理
window.addEventListener('scroll', throttle(handleScroll, 100));
// 页面加载完成后先执行一次,处理初始就在可视区域的元素
window.addEventListener('load', handleScroll);
优化建议
- 尽量使用节流或防抖处理scroll事件,减少不必要的逻辑执行,提升页面性能。
- 如果页面中需要触发动画的元素较多,可以使用Intersection Observer API替代scroll事件监听,该API是浏览器原生提供的观察元素进入可视区域的接口,性能更优。
- CSS动画尽量使用transform和opacity属性,这两个属性的动画不会触发页面的重排重绘,动画效果更流畅。
- 避免给动画元素设置过多的复杂样式,减少动画执行时的性能消耗。
常见问题解答
动画只触发一次怎么实现?
如上面的示例代码所示,在添加show类之前先判断元素是否已经包含该类,如果已经包含就不再重复添加,即可实现动画只触发一次的效果。
动画触发的位置可以调整吗?
可以,在isElementInViewport函数中调整判断条件即可,比如将rect.top的判断值改为window.innerHeight * 0.8,就可以让元素进入可视区域80%的位置时再触发动画。