You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面滚动动画切换异常求助:旧动画未清除

问题描述

我开发了一个页面,用户可从动画列表中选择一款动画,点击确认按钮后,该动画会应用到用户输入的目标标签上。首次操作一切正常,但当用户选择新动画时出现异常:

  • 正常效果:首次选择动画后,目标元素能正确触发对应动画
  • 异常效果:切换新动画后,旧动画未被清除,导致动画表现混乱

数据对象结构

[{
  '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');
        }

      }
    
    })
  }
}

问题根源与修复方案

核心问题

  1. 重复绑定scroll事件:每次调用page____scroll都会给.page_frame新增一个滚动监听器,旧监听器未被移除,导致多次触发动画逻辑,新旧动画规则冲突。
  2. 旧动画属性未彻底清除:remove____animation函数未完全重置目标元素的动画相关属性(如内联样式、data-animation状态),旧动画残留影响新动画表现。

修复步骤

  1. 全局管理滚动监听器,避免重复绑定
    定义全局变量存储监听器函数,每次调用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);
      }
    }
    
  2. 完善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;
    }
    
  3. 优化点击事件绑定方式
    原代码使用onclick赋值会覆盖旧事件,改为addEventListener确保只绑定一次:

    // 替换原绑定代码
    document.querySelector(".page_frame").addEventListener('click', preview);
    

内容的提问来源于stack exchange,提问作者Oss_vahid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:24:58