仅在可见时反应自动播放 <video /> (mp4)
React autoplay <video /> (mp4) only when visible
我正在编写一个组件,它从 Giphy 中提取 gif 图像并将它们呈现在 React Infinite Scroll 组件中。无限滚动按预期工作,但后来我 运行 遇到了问题。我想让 gif 自动播放,所以我添加了自动播放属性。然后我意识到,如果同时播放所有 gif,性能就会下降。
我尝试了多种不同的解决方案,包括为每个视频组件附加一个 ref 并使用 react-visibility-sensor 尝试在可见时播放,但我一直无法找到可行的方法。
这是当前与每个 mp4 自动播放一起使用的组件。我已经删除了 VisibilitySensor,因为我无法让它工作。
const videoRefs = useRef(
[...new Array(gifArray.length)].map(() => createRef()),
);
return (
<div>
{gifArray && (
<InfiniteScroll
dataLength={gifArray}
next={getMore}
hasMore={true}
loader={<div>Loading...</div>}
>
{gifArray.map((gif, i) => {
return (
<video
width='320'
height='240'
loop
autoPlay
key={gif.id}
ref={videoRefs.current[i]}
>
<source src={gif.images.downsized_small.mp4} type='video/mp4' />
</video>
);
})}
</InfiniteScroll>
)}
</div>
);
};
数据在单独的组件中检索并作为 props 传递。
export const HomePage = () => {
const [gifObject, setGifObject] = useState([]);
const [searchValue, setSearchValue] = useState('');
const [pageNumber, setPageNumber] = useState(0);
const handleSearch = (value) => {
setSearchValue(value);
fetch(
`http://api.giphy.com/v1/gifs/search?q=${value}&api_key=${API_KEY}&limit=20`,
)
.then((data) => data.json())
.then((result) => {
setGifObject(result);
});
};
return (
<div>
<SearchForm handleSearchValue={handleSearch} />
{gifObject?.data?.length > 1 ? (
<GifDisplay gifArray={gifObject.data} getMore={getData} />
) : null}
</div>
);
}
我最终解决了这个问题。
我为每个 gif 创建了一个组件,并使用一个名为 react-visibility-sensor
的包来检查它是否可见。
GifDisplay
组件保持非常接近相同:
// GifDisplay.tsx
export const GifDisplay = ({ gifArray, getMore, handleSearch }) => {
return (
<GifDisplayWrapper>
{gifArray && (
<InfiniteScroll
dataLength={gifArray}
next={getMore}
hasMore={true}
loader={<div>Loading...</div>}
>
<ArrayWrapper>
{gifArray.map((gif) => {
return (
<div key={gif.id}>
<SingleGif gif={gif} />
</div>
);
})}
</ArrayWrapper>
</InfiniteScroll>
)}
</GifDisplayWrapper>
);
};
SingleGif
组件使用了 react-visibility-sensor
并更新了每个组件的状态。
// SingleGif.tsx
import VisibilitySensor from 'react-visibility-sensor';
export const SingleGif = ({ gif }) => {
const videoRef = useRef(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
if (isVisible) {
videoRef.current.play();
} else {
if (videoRef.current.play) {
videoRef.current.pause();
}
}
}, [isVisible]);
return (
<VisibilitySensor onChange={(isVisible) => setIsVisible(isVisible)}>
<video width='320' height='240' loop ref={videoRef}>
<source src={gif.images.downsized_small.mp4} type='video/mp4' />
</video>
</VisibilitySensor>
);
};
使用 react-intersection-observer
而不是上面有人评论的 react-visibility-sensor
。 react-visibility-sensor
不再可用。
我正在编写一个组件,它从 Giphy 中提取 gif 图像并将它们呈现在 React Infinite Scroll 组件中。无限滚动按预期工作,但后来我 运行 遇到了问题。我想让 gif 自动播放,所以我添加了自动播放属性。然后我意识到,如果同时播放所有 gif,性能就会下降。
我尝试了多种不同的解决方案,包括为每个视频组件附加一个 ref 并使用 react-visibility-sensor 尝试在可见时播放,但我一直无法找到可行的方法。
这是当前与每个 mp4 自动播放一起使用的组件。我已经删除了 VisibilitySensor,因为我无法让它工作。
const videoRefs = useRef(
[...new Array(gifArray.length)].map(() => createRef()),
);
return (
<div>
{gifArray && (
<InfiniteScroll
dataLength={gifArray}
next={getMore}
hasMore={true}
loader={<div>Loading...</div>}
>
{gifArray.map((gif, i) => {
return (
<video
width='320'
height='240'
loop
autoPlay
key={gif.id}
ref={videoRefs.current[i]}
>
<source src={gif.images.downsized_small.mp4} type='video/mp4' />
</video>
);
})}
</InfiniteScroll>
)}
</div>
);
};
数据在单独的组件中检索并作为 props 传递。
export const HomePage = () => {
const [gifObject, setGifObject] = useState([]);
const [searchValue, setSearchValue] = useState('');
const [pageNumber, setPageNumber] = useState(0);
const handleSearch = (value) => {
setSearchValue(value);
fetch(
`http://api.giphy.com/v1/gifs/search?q=${value}&api_key=${API_KEY}&limit=20`,
)
.then((data) => data.json())
.then((result) => {
setGifObject(result);
});
};
return (
<div>
<SearchForm handleSearchValue={handleSearch} />
{gifObject?.data?.length > 1 ? (
<GifDisplay gifArray={gifObject.data} getMore={getData} />
) : null}
</div>
);
}
我最终解决了这个问题。
我为每个 gif 创建了一个组件,并使用一个名为 react-visibility-sensor
的包来检查它是否可见。
GifDisplay
组件保持非常接近相同:
// GifDisplay.tsx
export const GifDisplay = ({ gifArray, getMore, handleSearch }) => {
return (
<GifDisplayWrapper>
{gifArray && (
<InfiniteScroll
dataLength={gifArray}
next={getMore}
hasMore={true}
loader={<div>Loading...</div>}
>
<ArrayWrapper>
{gifArray.map((gif) => {
return (
<div key={gif.id}>
<SingleGif gif={gif} />
</div>
);
})}
</ArrayWrapper>
</InfiniteScroll>
)}
</GifDisplayWrapper>
);
};
SingleGif
组件使用了 react-visibility-sensor
并更新了每个组件的状态。
// SingleGif.tsx
import VisibilitySensor from 'react-visibility-sensor';
export const SingleGif = ({ gif }) => {
const videoRef = useRef(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
if (isVisible) {
videoRef.current.play();
} else {
if (videoRef.current.play) {
videoRef.current.pause();
}
}
}, [isVisible]);
return (
<VisibilitySensor onChange={(isVisible) => setIsVisible(isVisible)}>
<video width='320' height='240' loop ref={videoRef}>
<source src={gif.images.downsized_small.mp4} type='video/mp4' />
</video>
</VisibilitySensor>
);
};
使用 react-intersection-observer
而不是上面有人评论的 react-visibility-sensor
。 react-visibility-sensor
不再可用。