使用$(window).scroll时页面顶部滚动重复动画的修复方法
问题:页面顶部加载后滚动时视口内元素重复触发动画
问题现象
页面从顶部位置加载后,向下滚动时,已处于视口内的<section>元素会再次触发动画,出现闪回效果;但页面从非顶部位置加载时,元素不会重复触发动画,表现正常。
现有尝试与问题
尝试通过判断父元素的animate-section和animate类来阻止重复触发,但逻辑存在问题:移除动画类后立刻重新添加,导致判断无效,无法阻止重复动画。临时采用了页面加载在顶部时滚动1px的hack,但希望找到正规修复方案。
正规修复方案
核心思路是标记已完成动画的元素,后续滚动事件不再处理这些元素,避免重复触发。以下是修改后的代码:
$(document).ready(function() { // 初始化:处理页面加载时已在视口内的元素 var sections = $('.animate-section'); sections.each(function() { if ($(this).isInViewport()) { $(this).addClass('animate'); // 标记该section内的动画元素为已完成,并触发初始动画 $(this).find('.animate-element') .addClass('animated-completed') .css("visibility", "visible") .addClass('animate'); } else { $(this).removeClass('animate'); } }); // 滚动事件:仅处理未完成动画的元素 var elements = $('.animate-element:not(.animated-completed)'); $(window).scroll(function() { elements.each(function() { var $el = $(this); if ($el.isInViewport()) { $el.css("visibility", "visible") .addClass('animate') .addClass('animated-completed'); // 将已完成的元素从监听集合中移除,优化性能 elements = elements.not($el); } else { $el.css("visibility", "hidden").removeClass('animate'); } }); }); }); // 元素视口检测函数 $.fn.isInViewport = function() { var elementTop = $(this).offset().top; var elementBottom = elementTop + $(this).outerHeight(); var viewportTop = $(window).scrollTop(); var viewportBottom = viewportTop + $(window).height(); return elementBottom > viewportTop && elementTop < viewportBottom; };
修复逻辑说明
- 初始化标记:页面加载完成后,对已在视口内的元素添加
animated-completed类,标记为已完成动画,同时设置可见性并触发初始动画。 - 滚动事件过滤:仅选择未标记的元素进行滚动监听,避免重复处理已完成动画的元素。
- 动态移除监听:元素完成动画后,从监听集合中移除,减少后续滚动事件的处理量,提升性能。
移除临时hack
采用上述方案后,无需再使用页面加载时滚动1px的hack代码,可直接删除相关逻辑。
内容的提问来源于stack exchange,提问作者TheAmazingKnight
相关产品推荐
相关产品推荐

