如何实现fade类元素仅一次的屏幕可见淡入、离开淡出动画?
解决方案:实现元素首次出现淡入、离开淡出且仅执行一次动画
问题说明
需要实现:带有fade类的元素首次出现在屏幕上时淡入,离开屏幕时淡出,且整个动画流程仅执行一次。
原尝试代码
.fade { /* transition: opacity 0.9s ease-in;*/ opacity: 0; } .fade.visible { transition: opacity 0.9s ease-in; opacity: 1; }
window.addEventListener('scroll', fade) function fade() { let animation=document.querySelectorAll('.fade'); for (let i=0; i<animation.length; i++) { let windowheight=window.innerHeight; let top=animation[i].getBoundingClientRect().top; if (top < windowheight) { animation[i].classList.add('visible'); } else { animation[i].classList.remove('visible'); } } }
修改后的实现代码
CSS 部分
.fade { opacity: 0; transition: opacity 0.9s ease-in; /* 把过渡放到基础类,淡入淡出都生效 */ } .fade.visible { opacity: 1; } .fade.faded-out { opacity: 0; }
JavaScript 部分
// 初始化观察器配置 const observerOptions = { root: null, // 使用视口作为根元素 rootMargin: '0px', threshold: 0.1 // 元素10%进入视口时触发 }; // 定义观察回调函数 function handleIntersection(entries, observer) { entries.forEach(entry => { const element = entry.target; if (entry.isIntersecting) { // 元素进入视口,添加visible类实现淡入 element.classList.add('visible'); // 切换观察逻辑,监听元素离开视口的事件 observer.unobserve(element); setTimeout(() => { observer.observe(element); }, 100); // 延迟避免立即触发离开事件 } else { // 元素离开视口,添加faded-out类实现淡出 element.classList.add('faded-out'); // 停止观察该元素,确保动画仅执行一次 observer.unobserve(element); } }); } // 创建观察器实例 const observer = new IntersectionObserver(handleIntersection, observerOptions); // 监听所有带fade类的元素 document.querySelectorAll('.fade').forEach(el => { observer.observe(el); });
关键修改点说明
- 替换滚动监听为IntersectionObserver:相比scroll事件的高频触发,IntersectionObserver性能更优,只在元素进入/离开视口时触发回调。
- 动画仅执行一次:元素首次进入视口淡入后,切换监听逻辑,待其离开时执行淡出,之后立即停止观察该元素,避免后续滚动重复触发动画。
- CSS过渡优化:将
transition属性放到.fade基础类中,确保淡入和淡出都能应用过渡效果,无需在不同类中重复定义。
内容的提问来源于stack exchange,提问作者engr. hasnat
相关产品推荐
相关产品推荐

