页面滚动动画切换异常求助:旧动画未清除
问题描述
我开发了一个页面,用户可从动画列表中选择一款动画,点击确认按钮后,该动画会应用到用户输入的目标标签上。首次操作一切正常,但当用户选择新动画时出现异常:
- 正常效果:首次选择动画后,目标元素能正确触发对应动画
- 异常效果:切换新动画后,旧动画未被清除,导致动画表现混乱
数据对象结构
[{ 'target_tag': '.box-1', 'animation_status': 'animation-1', ... }, { 'target_tag': '.box-2', 'animation_status': 'animation-2', ... }]
处理函数
document.querySelector(".page_frame").onclick = preview; function preview() { var data = ''; // ------------- 检查输入框是否为空 var feilds = jQuery(".sts_create input").filter('[type="text"]'); for (var i = 0; i < feilds.length; i++) { if (feilds[i].value == "") { new novaAlert({ icon: "danger", title: "خطا", text: "یک یا چند کادر خالی یافت شد لطفا تمامی کادر هارا با دقت پر کنید", confirmButtonText: "متوجه شدم", dismissButton: false, }).then(); } } const sts_mode = jQuery('.sts_create input[type="radio"]:checked').val(); // alert(sts_mode) const obj = jQuery(".sts_create form").serializeArray(); const collate = (obj) => { const result = [{}]; for (const [_, input_info] of Object.entries(obj)) { // 检查结果数组的最后一项是否已有当前输入名称的属性,有则新增对象 if ( input_info.name != "target_page_name" && input_info.name != "target_page" && input_info.name != "sts_mode" ) { if (result[result.length - 1].hasOwnProperty(input_info.name)) result.push({}); // 给结果数组末尾的对象添加属性 result[result.length - 1][input_info.name] = input_info.value; } } // 将结果数组转为对象 return Object.fromEntries(Object.entries(result)); }; data = collate(obj); let x = ""; console.log(data); for (var item in data) { x = data[item]; if(remove____animation(x.target_tag)) { if (sts_mode == "show-after-page-load") { page____load(x); } else if (sts_mode == "show-when-element-seeing") { page____scroll(x); } } } }
滚动触发动画主函数
function page____scroll(obj){ if (obj.target_tag != "") { document.querySelector('.page_frame').addEventListener('scroll',()=>{ var all_elements = jQuery( ".frame " + obj.target_tag ); for (var i = 0; i < all_elements.length; i++) { var _innerHeight = window.innerHeight; var elm = all_elements[i].getBoundingClientRect().top; if (elm < _innerHeight - 200) { jQuery(all_elements[i]).css("animation-duration", obj.duration); jQuery(all_elements[i]).css( "animation-delay", obj.animation_delay ) jQuery(all_elements[i]).attr('data-animation',obj.animation_status); } else if(obj.sts_show_again == 'on') { jQuery(all_elements[i]).attr('data-animation','hidden'); } } }) } }
问题根源与修复方案
核心问题
- 重复绑定scroll事件:每次调用
page____scroll都会给.page_frame新增一个滚动监听器,旧监听器未被移除,导致多次触发动画逻辑,新旧动画规则冲突。 - 旧动画属性未彻底清除:
remove____animation函数未完全重置目标元素的动画相关属性(如内联样式、data-animation状态),旧动画残留影响新动画表现。
修复步骤
全局管理滚动监听器,避免重复绑定
定义全局变量存储监听器函数,每次调用page____scroll前先移除旧监听器,再添加新的:// 全局存储滚动监听器 let scrollAnimationListener = null; function page____scroll(obj){ if (obj.target_tag != "") { // 移除旧监听器 if(scrollAnimationListener) { document.querySelector('.page_frame').removeEventListener('scroll', scrollAnimationListener); } // 定义新的监听器逻辑 scrollAnimationListener = ()=>{ var all_elements = jQuery(".frame " + obj.target_tag); for (var i = 0; i < all_elements.length; i++) { var _innerHeight = window.innerHeight; var elm = all_elements[i].getBoundingClientRect().top; if (elm < _innerHeight - 200) { jQuery(all_elements[i]).css({ "animation-duration": obj.duration, "animation-delay": obj.animation_delay }).attr('data-animation', obj.animation_status); } else if(obj.sts_show_again == 'on') { jQuery(all_elements[i]).attr('data-animation','hidden'); } } } // 添加新监听器 document.querySelector('.page_frame').addEventListener('scroll', scrollAnimationListener); } }完善
remove____animation函数,彻底清除旧动画function remove____animation(targetTag) { const elements = jQuery(".frame " + targetTag); if(elements.length === 0) return false; // 重置动画状态与内联样式 elements.attr('data-animation', 'hidden') .css({ 'animation-duration': '', 'animation-delay': '', 'animation-name': '' // 若有直接设置动画名称也需清除 }); return true; }优化点击事件绑定方式
原代码使用onclick赋值会覆盖旧事件,改为addEventListener确保只绑定一次:// 替换原绑定代码 document.querySelector(".page_frame").addEventListener('click', preview);
内容的提问来源于stack exchange,提问作者Oss_vahid
相关产品推荐
相关产品推荐

