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

React中如何控制Framer Motion等动画播放暂停,适配视频同步需求

React中视频与叠加动画同步控制的实现方案

核心逻辑为监听video元素的play/pause事件,同步修改动画的播放状态,完全在前端运行时控制,无需修改视频源文件,符合不使用FFmpeg的要求。


方案1:Framer Motion实现

  • 核心使用useAnimation钩子获取动画控制实例,调用对应方法即可实现播放、暂停控制
  • 代码示例:
import { useRef, useEffect } from 'react';
import { motion, useAnimation } from 'framer-motion';

function VideoWithOverlay() {
  const videoRef = useRef(null);
  const controls = useAnimation();

  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    const handlePlay = () => controls.start();
    // Framer Motion v7+ 可替换为controls.pause()实现从暂停位置续播
    const handlePause = () => controls.stop();

    video.addEventListener('play', handlePlay);
    video.addEventListener('pause', handlePause);
    return () => {
      video.removeEventListener('play', handlePlay);
      video.removeEventListener('pause', handlePause);
    };
  }, [controls]);

  return (
    <div style={{ position: 'relative', width: '800px' }}>
      <video ref={videoRef} controls style={{ width: '100%' }}>
        <source src="你的视频地址" type="video/mp4" />
      </video>
      {/* 叠加动画元素示例 */}
      <motion.div
        style={{
          position: 'absolute',
          top: '20%',
          left: '30%',
          width: '50px',
          height: '50px',
          borderRadius: '50%',
          background: 'rgba(255,255,255,0.7)',
        }}
        animate={controls}
        variants={{
          start: {
            y: [0, -30, 0],
            opacity: [0.7, 1, 0.7],
            transition: { repeat: Infinity, duration: 2, ease: 'easeInOut' }
          }
        }}
      />
    </div>
  );
}

方案2:GSAP实现

  • GSAP的补间动画/时间线实例原生支持play()/pause()方法,控制粒度更细,适合复杂多元素动画场景
  • 代码示例:
import { useRef, useEffect } from 'react';
import gsap from 'gsap';

function VideoWithOverlay() {
  const videoRef = useRef(null);
  const animRef = useRef(null);
  const tlRef = useRef(null);

  useEffect(() => {
    // 初始化循环动画时间线,默认暂停
    tlRef.current = gsap.timeline({ repeat: -1, paused: true })
      .to(animRef.current, { y: -30, opacity: 1, duration: 1, ease: 'power1.inOut' })
      .to(animRef.current, { y: 0, opacity: 0.7, duration: 1, ease: 'power1.inOut' });

    const video = videoRef.current;
    if (!video) return;

    const handlePlay = () => tlRef.current.play();
    const handlePause = () => tlRef.current.pause();

    video.addEventListener('play', handlePlay);
    video.addEventListener('pause', handlePause);
    return () => {
      video.removeEventListener('play', handlePlay);
      video.removeEventListener('pause', handlePause);
      tlRef.current.kill(); // 销毁动画避免内存泄漏
    };
  }, []);

  return (
    <div style={{ position: 'relative', width: '800px' }}>
      <video ref={videoRef} controls style={{ width: '100%' }}>
        <source src="你的视频地址" type="video/mp4" />
      </video>
      <div
        ref={animRef}
        style={{
          position: 'absolute',
          top: '20%',
          left: '30%',
          width: '50px',
          height: '50px',
          borderRadius: '50%',
          background: 'rgba(255,255,255,0.7)',
          opacity: 0.7
        }}
      />
    </div>
  );
}

方案3:Lottie实现

如果使用设计师导出的JSON格式动效,Lottie是最优选择,lottie-react库原生支持播放暂停控制

  • 代码示例:
import { useRef, useEffect } from 'react';
import Lottie from 'lottie-react';
import animationData from './你的动效文件.json';

function VideoWithOverlay() {
  const videoRef = useRef(null);
  const lottieRef = useRef(null);

  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    const handlePlay = () => lottieRef.current?.play();
    const handlePause = () => lottieRef.current?.pause();

    video.addEventListener('play', handlePlay);
    video.addEventListener('pause', handlePause);
    return () => {
      video.removeEventListener('play', handlePlay);
      video.removeEventListener('pause', handlePause);
    };
  }, []);

  return (
    <div style={{ position: 'relative', width: '800px' }}>
      <video ref={videoRef} controls style={{ width: '100%' }}>
        <source src="你的视频地址" type="video/mp4" />
      </video>
      <div style={{ position: 'absolute', top: '20%', left: '30%', width: '100px' }}>
        <Lottie
          lottieRef={lottieRef}
          animationData={animationData}
          loop={true}
          autoplay={false} // 关闭自动播放,由视频状态控制
        />
      </div>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 22:30:05