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

求React实现类似Framer官网的无限图片流动动画(CSS/JS)方案

实现类似Framer官网的无限图片流动动画(React + CSS + JS方案)

核心实现思路

Framer官网的主视觉无限图片流核心是横向无缝循环滚动+分层视觉效果,关键逻辑:

  • 采用「双容器复用」技巧:创建两个完全相同的图片列表容器,当第一个容器完全滚出视口时,将其重置到第二个容器的末尾,实现无感知的无限循环
  • 通过CSS的transform(位移、缩放)和opacity属性,给不同图片设置差异化的大小、透明度,模拟空间深度感
  • 用JS驱动滚动动画,通过requestAnimationFrame保证动画流畅度,避免CSS动画在复杂场景下的卡顿

代码实现示例

React组件结构

import { useRef, useEffect, useState } from 'react';

const InfiniteImageFlow = () => {
  const containerRef = useRef(null);
  const [images, setImages] = useState([
    // 替换成你的图片地址,建议使用不同比例的图片增强层次感
    '/img1.jpg', '/img2.jpg', '/img3.jpg', '/img4.jpg', '/img5.jpg'
  ]);
  const scrollPosition = useRef(0);
  const animationRef = useRef(null);

  // 生成重复的图片列表(双容器复用)
  const doubledImages = [...images, ...images];

  useEffect(() => {
    const animate = () => {
      if (!containerRef.current) return;
      // 控制滚动速度,数值越小越慢
      scrollPosition.current -= 0.5;
      // 当滚动距离达到单个容器宽度时重置,实现循环
      const singleContainerWidth = containerRef.current.offsetWidth / 2;
      if (Math.abs(scrollPosition.current) >= singleContainerWidth) {
        scrollPosition.current = 0;
      }
      containerRef.current.style.transform = `translateX(${scrollPosition.current}px)`;
      animationRef.current = requestAnimationFrame(animate);
    };

    animationRef.current = requestAnimationFrame(animate);

    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, []);

  return (
    <div className="image-flow-wrapper">
      <div ref={containerRef} className="image-flow-container">
        {doubledImages.map((img, idx) => (
          <div key={idx} className="image-item">
            <img src={img} alt={`flow-img-${idx}`} />
          </div>
        ))}
      </div>
    </div>
  );
};

export default InfiniteImageFlow;

CSS样式

.image-flow-wrapper {
  position: relative;
  width: 100%;
  height: 600px; /* 对应主视觉区域高度 */
  overflow: hidden;
  background: #000;
}

.image-flow-container {
  position: absolute;
  top: 50%;
  left: 0;
  display: flex;
  gap: 2rem;
  transform: translateY(-50%);
  will-change: transform; /* 告诉浏览器提前优化动画 */
}

.image-item {
  flex-shrink: 0;
  /* 自适应大小,兼顾不同屏幕 */
  width: clamp(200px, 30vw, 400px);
  opacity: 0.6;
}

.image-item img {
  width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}

/* 给不同位置的图片设置差异化样式,增强层次感 */
.image-item:nth-child(2n) {
  transform: translateY(-10%) scale(0.9);
  opacity: 0.8;
}

.image-item:nth-child(3n) {
  transform: translateY(10%) scale(1.1);
  opacity: 0.7;
}

关键技术优化建议

  • 性能优化:
    • 给动画容器添加will-change: transform,触发GPU加速,减少页面重绘
    • 图片优先使用WebP格式压缩体积,避免大资源拖慢动画
    • 始终用requestAnimationFrame替代setInterval,保证动画与浏览器刷新同步
  • 视觉增强:
    • 通过JS动态给每个图片生成随机的translateY、scale、opacity值,比CSS伪类控制更自然
    • 可添加鼠标交互:监听鼠标移动位置,让图片滚动速度随鼠标偏移实时变化
  • 响应式适配:
    • 使用clamp()、vw单位设置图片大小,自动适配不同屏幕宽度
    • 在小屏设备上降低滚动速度,避免视觉杂乱
  • 图片加载:
    • 实现图片懒加载,避免初始加载过多资源
    • 给图片添加占位骨架,提升用户等待体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:21:07