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

ReactJS实现滚动时视口中心视频播放、其余暂停的功能

实现滚动时自动播放视口中心视频并暂停其他视频的方案

要实现这个需求,我们需要结合元素位置检测和滚动监听来管理所有视频的播放状态。下面是修改后的完整代码,我会逐点拆解关键逻辑:

import { useState, useEffect, useRef } from 'react';
import MDBox from '...'; // 确保导入项目中对应的组件
import Card from '...';

const VideoReels = () => {
  const [reels, setReels] = useState([]);
  const videoRefs = useRef([]); // 存储所有视频元素的DOM引用

  useEffect(() => {
    fetchAllVideos();
    // 挂载时添加滚动监听
    window.addEventListener('scroll', handleScroll);
    // 组件卸载时清理监听,避免内存泄漏
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  const fetchAllVideos = async () => {
    const getAllVideosRes = await getAllVideos(pageNumber);
    setReels(getAllVideosRes);
  };

  // 判断视频是否落在视口中心区域
  const isVideoInCenter = (videoElement) => {
    if (!videoElement) return false;
    const rect = videoElement.getBoundingClientRect();
    const viewportHeight = window.innerHeight;
    // 定义视口中心范围:上下各留1/4高度,可根据需求调整
    const centerTop = viewportHeight / 4;
    const centerBottom = viewportHeight * 3 / 4;
    // 取视频垂直中心位置判断是否在范围内
    const videoCenterY = rect.top + rect.height / 2;
    return videoCenterY >= centerTop && videoCenterY <= centerBottom;
  };

  const handleScroll = () => {
    // 先找到处于视口中心的视频索引
    let activeVideoIndex = -1;
    videoRefs.current.forEach((video, index) => {
      if (isVideoInCenter(video)) {
        activeVideoIndex = index;
      }
    });

    // 控制播放状态:播放中心视频,暂停其余所有
    videoRefs.current.forEach((video, index) => {
      if (!video) return;
      if (index === activeVideoIndex) {
        video.play().catch(err => console.error('视频播放失败:', err));
      } else {
        video.pause();
      }
    });
  };

  return (
    <>
      {reels.map((item, idx) => (
        <MDBox mb={3} key={idx}>
          <Card sx={{ borderRadius: "25px" }}>
            <video
              ref={el => videoRefs.current[idx] = el} // 给每个视频绑定DOM引用
              style={{ 
                height: "100%", 
                width: "100%", 
                objectFit: "cover", 
                borderRadius: "25px" 
              }}
              loop
              muted // 浏览器限制:非静音视频无法自动播放
              playsInline // 移动端避免自动全屏播放
            >
              <source src={item.photo} type="video/mp4" />
            </video>
          </Card>
        </MDBox>
      ))}
    </>
  );
};

export default VideoReels;

关键逻辑说明

  • 视频引用管理:用useRef创建数组存储所有视频的DOM引用,方便直接操作播放/暂停。
  • 滚动监听生命周期:组件挂载时绑定滚动事件,卸载时移除,避免无用监听占用资源。
  • 视口中心判断:通过getBoundingClientRect()获取视频位置,计算视口中心区域,判断视频垂直中心是否落在该区域内。
  • 播放状态控制:滚动时遍历所有视频,找到中心视频后播放,同时暂停其他所有视频。
  • 浏览器兼容处理:添加muted和playsInline属性,解决浏览器自动播放限制和移动端全屏问题。

可选优化点

  • 给handleScroll添加节流处理(比如用lodash.throttle),减少滚动时的函数触发频率,提升性能。
  • 视频加载完成后(监听onLoadedData事件),主动调用一次handleScroll,确保初始状态下中心视频自动播放。
  • 可根据布局需求调整centerTop和centerBottom的数值,自定义视口中心的范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:21:23