In maplist I have 20 items that is 20 videos I want to do is play video which comes in center of viewport and pause all others and keep that behaviour throughout scrolling:
const [reels, setReels] = useState([]);
useEffect(() => {
fetchAllVideos();
}, []);
const fetchAllVideos = async () => {
const getAllVideosRes = await getAllVideos(pageNumber);
setReels(getAllVideosRes);
};
return (
<>
reels.map((item, idx) => {
return (
<MDBox mb={3} key={idx}>
<Card sx={{ borderRadius: "25px" }}>
<video style={{ height: "100%", width: "100%", objectFit: "cover", borderRadius: "25px", }} loop controls>
<source src={item.photo} type="video/mp4" />
</video>
</MDBox>
</Card>
</MDBox >
);
})
</>
)
Use an intersectionObserver to track the items as they enter or leave the container.
Set the threshold to be 100% of the element (threshold: 1
), and the rootMargin
to limit the intersection area to the center of the container (rootMargin: '-20% 0% -20% 0%'
).
const { useRef, useState, useEffect, useCallback } = React
const usePlayIntersection = () => {
const containerRef = useRef();
const [observer, setObserver] = useState();
useEffect(() => {
const cb = entries => {
entries.forEach(({ isIntersecting, target, intersectionRect }) => {
if(isIntersecting) target.play()
else target.pause()
})
};
const obs = new IntersectionObserver(cb, {
root: containerRef.current,
rootMargin: '-20% 0% -20% 0%',
threshold: 1
})
setObserver(obs)
return () => {
obs.disconnect()
}
}, [])
const observe = useCallback(el => {
if(observer) observer.observe(el)
}, [observer])
return [observe, containerRef]
}
const Demo = ({ videos }) => {
const [observe, containerRef] = usePlayIntersection();
return (
<div className="container" ref={containerRef}>
<div className="filler" />
{videos.map(vid => (
<video
ref={observe}
muted
key={vid}
loop controls>
<source src={vid} type="video/mp4" />
</video>
))}
<div className="filler" />
</div>
)
}
const videos = ["http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/VolkswagenGTIReview.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/WeAreGoingOnBullrun.mp4","http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/WhatCarCanYouGetForAGrand.mp4"]
ReactDOM
.createRoot(root)
.render(<Demo videos={videos} />)
html, body {
margin: 0;
padding: 0;
}
.container {
height: 100vh;
overflow: auto;
}
video, .filler {
display: block;
margin: 1em;
height: 40%;
width: 40%;
objectFit: cover;
borderRadius: 25px;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>