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

React中滚动触发CSS动画的最优方案咨询(仿agap2.fr缩放效果)

滚动触发CSS动画的更优实现方案

你当前通过useEffect监听scroll事件手动修改样式的方式可行,但存在性能损耗(滚动事件高频触发),且代码冗余。下面是几种更简洁高效的实现方案:

1. 原生CSS scroll-timeline(最优推荐)

这是浏览器原生支持的滚动驱动动画方案,完全无需JS参与,性能最优且代码极简:

/* 定义滚动时间线,绑定页面垂直滚动 */
@scroll-timeline circle-scale-timeline {
  source: auto;
  orientation: vertical;
  /* 动画触发的滚动范围:从目标元素进入视口到完全离开 */
  scroll-offsets: 
    calc(100vh - 50px) 0%, /* 元素顶部接触视口底部时开始 */
    0% 100%; /* 元素底部离开视口顶部时结束 */
}

/* 圆形元素基础样式 */
.circle {
  position: fixed;
  width: 50px;
  height: 50px;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  background-color: #ff0;
  border-radius: 999px;
  box-sizing: border-box;
}

/* 绑定滚动驱动的缩放动画 */
.circle {
  animation: scale-animation linear;
  animation-timeline: circle-scale-timeline;
}

@keyframes scale-animation {
  from { width: 50px; height: 50px; }
  to { width: 300px; height: 300px; }
}

JSX只需渲染基础元素:

<div className="circle" />

2. Intersection Observer API(JS高效方案)

如果需要基于元素可见性触发动画,用这个API比直接监听scroll更高效——它仅在元素可见性变化时触发回调,避免高频触发:

import { useEffect, useRef } from 'react';

function Circle() {
  const circleRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach(entry => {
          // 根据可见状态切换动画类
          entry.target.classList.toggle('scale-active', entry.isIntersecting);
        });
      },
      { threshold: 0.1 } // 元素10%可见时触发
    );

    circleRef.current && observer.observe(circleRef.current);
    return () => circleRef.current && observer.unobserve(circleRef.current);
  }, []);

  return (
    <div ref={circleRef} className="circle" />
  );
}

配套CSS:

.circle {
  position: fixed;
  width: 50px;
  height: 50px;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  background-color: #ff0;
  border-radius: 999px;
  box-sizing: border-box;
  transition: width 0.3s, height 0.3s;
}

.scale-active {
  width: 300px;
  height: 300px;
}

3. React动画库(快速开发)

如果是React项目,用封装好的动画库(如framer-motion)可以快速实现滚动驱动动画,库内部已做防抖节流等性能优化:

import { motion } from 'framer-motion';

function Circle() {
  return (
    <motion.div
      className="circle"
      initial={{ width: 50, height: 50 }}
      // 根据滚动位置动态调整尺寸
      animate={{ 
        width: window.scrollY > 600 ? 300 : 50,
        height: window.scrollY > 600 ? 300 : 50
      }}
      transition={{ duration: 0.3 }}
    />
  );
}

方案对比

  • CSS scroll-timeline:无JS依赖,性能拉满,代码最简洁,优先推荐
  • Intersection Observer:适合需要精准控制可见性触发的场景,比scroll监听高效
  • React动画库:快速开发首选,减少重复造轮子

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:40:40