滚动触发卡片加载动画:如何避免卡片元素无限重复创建?
解决方案
核心问题是scroll事件触发频率极高,满足阈值条件后会反复执行创建卡片逻辑,只需新增创建状态锁避免重复执行即可,以下是两种纯原生JS的实现方案:
方案1:基于原有scroll监听改造(改动最小)
- 新增全局状态变量标记卡片是否已创建,创建完成后锁死逻辑不再重复执行
- 用元素
getBoundingClientRect()动态计算项目标题位置,避免硬编码滚动阈值
示例代码:
// 状态锁:初始为false,代表卡片未创建 let isCardsCreated = false; // 替换为你项目板块标题的实际选择器 const projectTitle = document.querySelector('.project-section-title'); // 你的项目数据数组 const projects = [/* 原有项目数据 */]; // 原有创建卡片函数,创建完成后直接加animated-bg类 function createProjectCard(projectList) { const cardContainer = document.querySelector('.card-container'); // 清空容器避免残留内容 cardContainer.innerHTML = ''; projectList.forEach(item => { const card = document.createElement('div'); card.className = 'project-card'; // 填充卡片内容的原有逻辑 card.innerText = item.desc; // 创建完成后加动画类 card.classList.add('animated-bg'); cardContainer.appendChild(card); }) } // 滚动监听逻辑 window.addEventListener('scroll', () => { // 卡片已创建则直接退出,不执行后续逻辑 if (isCardsCreated) return; // 项目标题顶部进入视口时触发创建 if (projectTitle.getBoundingClientRect().top < window.innerHeight) { createProjectCard(projects); // 锁死状态,后续滚动不会再触发 isCardsCreated = true; } })
方案2:用IntersectionObserver实现(性能更优)
无需监听高频scroll事件,用浏览器原生交叉观察器监听元素进入视口的时机,性能开销更低:
let isCardsCreated = false; const projectTitle = document.querySelector('.project-section-title'); const projects = [/* 原有项目数据 */]; function createProjectCard(projectList) { // 同方案1的创建逻辑 } // 初始化交叉观察器 const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { // 项目标题进入视口且卡片未创建时执行逻辑 if (entry.isIntersecting && !isCardsCreated) { createProjectCard(projects); isCardsCreated = true; // 停止监听,释放资源 observer.unobserve(projectTitle); } }) }) // 开始监听项目标题元素 observer.observe(projectTitle);
内容的提问来源于stack exchange,提问作者awelie_go
相关产品推荐
相关产品推荐

