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

移动端IntersectionObserver触发滚动动画延迟问题求助

移动端快速滚动时IntersectionObserver触发动画延迟问题

我通过IntersectionObserver实现了元素可见时触发文字动画的功能,但在移动端快速滚动到目标div时,动画无法立即触发,存在明显延迟。

相关代码

JavaScript 动画触发函数

export function scrollAnimation(selector, options = {}) {
  let component = document.querySelectorAll(selector);
  component = Array.from(component);
  component.forEach((comp) => {
    addObserver(comp, options);
    // comp.addEventListener("animationend", function () {
    //   comp.classList.remove("active");
    // });
  });
}

function addObserver(comp, options) {
  let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.classList.add("active");
        // observer.unobserve(entry.target);
      } else {
        // setTimeout(() => {
        entry.target.classList.remove("active");
        // }, "250");
      }
    });
  }, options);
  observer.observe(comp);
}

React 组件调用代码

useEffect(() => {
  scrollAnimation(".animate", {
    rootMargin: "0px",
    threshold: 0,
  });
  const isVerified = localStorage.getItem("isVerified");
  setIsAgeVerifyModal(!isVerified);
}, [location]);

CSS 动画样式

.active {
  animation-name: fadeInUp;
  animation-duration: 0.75s;
  animation-fill-mode: both;
}

@keyframes fadeInUp {
  0% {
    opacity: 0;
    transform: translate3d(100%, 0, 0);
  }
  100% {
    opacity: 1;
    transform: translateZ(0);
  }
}

补充:尝试制作JS Fiddle示例时发现keyframes存在兼容性问题。


解决办法

  1. 优化IntersectionObserver配置

    • 修改rootMargin为-50px 0,让元素提前50px进入检测范围,抵消滚动延迟;将threshold设为0.1,当元素10%进入视口时触发动画,比0更灵敏:
      scrollAnimation(".animate", {
        rootMargin: "-50px 0px",
        threshold: 0.1,
      });
      
  2. 调整动画触发逻辑

    • 元素离开视口时添加延迟再移除active类,避免快速滚动时动画频繁启停:
      function addObserver(comp, options) {
        let observer = new IntersectionObserver((entries) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              entry.target.classList.add("active");
            } else {
              const timer = setTimeout(() => {
                if (!entry.isIntersecting) {
                  entry.target.classList.remove("active");
                }
              }, 300);
              // 清理定时器防止内存泄漏
              entry.target._timer && clearTimeout(entry.target._timer);
              entry.target._timer = timer;
            }
          });
        }, options);
        observer.observe(comp);
      }
      
  3. 提升CSS动画性能

    • 简化transform属性,改用translateX替代translate3d,减少GPU渲染开销:
      @keyframes fadeInUp {
        0% {
          opacity: 0;
          transform: translateX(100%);
        }
        100% {
          opacity: 1;
          transform: translateX(0);
        }
      }
      
    • 给目标元素添加will-change提示浏览器优化:
      .animate {
        will-change: transform, opacity;
      }
      
  4. 合并Observer实例

    • 原代码每个元素创建一个Observer,改成单个实例监听所有元素,降低性能消耗:
      export function scrollAnimation(selector, options = {}) {
        const components = Array.from(document.querySelectorAll(selector));
        const observer = new IntersectionObserver((entries) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              entry.target.classList.add("active");
            } else {
              const timer = setTimeout(() => {
                if (!entry.isIntersecting) {
                  entry.target.classList.remove("active");
                }
              }, 300);
              entry.target._timer && clearTimeout(entry.target._timer);
              entry.target._timer = timer;
            }
          });
        }, options);
        components.forEach(comp => observer.observe(comp));
      }
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:14:51