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
相关产品推荐
相关产品推荐

