admin管理员组文章数量:1125362
I created a video listing similar to TikTok and YouTube shorts using the 'react-window-infinite-loader', 'react-window', 'react-virtualized-auto-sizer', and 'video.js'. When I set the item snap, it works fine on the Chrome browser but not properly with the Safari browser. After 2 items, when I snap the third item, it automatically bounces back to 2 items.
Here are the code sandbox example links
=%2Fsrc%2FApp.js%3A1%2C1-114%2C1
/
import React, { useRef, useState, memo } from "react";
import { FixedSizeList, areEqual } from "react-window";
import InfiniteLoader from "react-window-infinite-loader";
import AutoSizer from "react-virtualized-auto-sizer";
import VideoJS from "./video";
import "./styles.css";
// Row component
const Row = memo(({ index, style, data }) => {
const { videoList, isItemLoaded, handlePlayerReady } = data;
// Render loading state
if (!isItemLoaded(index)) {
return (
<div
style={{
...style,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
Loading...
</div>
);
}
const video = videoList[index];
const videoJsOptions = {
autoplay: true,
controls: true,
muted: true,
playsinline: true,
sources: [{ src: video.src, type: video.type }],
};
return (
<div
style={{
...style,
scrollSnapAlign: "start",
scrollBehavior: "smooth",
}}
>
<VideoJS options={videoJsOptions} onReady={handlePlayerReady} />
</div>
);
}, areEqual);
export default function App() {
const [videoList, setVideoList] = useState(
Array(20)
.fill()
.map((_, index) => ({
id: index,
src: ".m3u8",
type: "application/x-mpegurl",
}))
);
const playerRef = useRef(null);
const handlePlayerReady = (player) => {
playerRef.current = player;
player.on("waiting", () => console.log("player is waiting"));
player.on("dispose", () => console.log("player will dispose"));
};
const loadMoreItems = async () => {
const newVideos = Array(10)
.fill()
.map((_, index) => ({
id: videoList.length + index,
src: ".m3u8",
type: "application/x-mpegurl",
}));
setTimeout(() => setVideoList((prev) => [...prev, ...newVideos]), 1000);
};
const isItemLoaded = (index) => index < videoList.length;
return (
<div style={{ height: "100vh", overflow: "hidden" }}>
<InfiniteLoader
isItemLoaded={isItemLoaded}
loadMoreItems={loadMoreItems}
itemCount={videoList.length + 1}
>
{({ onItemsRendered, ref }) => (
<AutoSizer>
{({ width, height }) => (
<FixedSizeList
height={height}
width={width}
itemCount={videoList.length}
itemSize={550}
onItemsRendered={onItemsRendered}
ref={ref}
itemData={{ videoList, isItemLoaded, handlePlayerReady }}
style={{
scrollSnapType: "y mandatory",
WebkitScrollSnapType: "y mandatory",
overflow: "auto",
}}
>
{Row}
</FixedSizeList>
)}
</AutoSizer>
)}
</InfiniteLoader>
</div>
);
}
import React from "react";
import videojs from "video.js";
import "video.js/dist/video-js.css";
import de from "video.js/dist/lang/de.json";
export const VideoJS = (props) => {
videojs.addLanguage("de", de);
const videoRef = React.useRef(null);
const playerRef = React.useRef(null);
const { options, onReady } = props;
React.useEffect(() => {
// make sure Video.js player is only initialized once
if (!playerRef.current) {
const videoElement = videoRef.current;
if (!videoElement) return;
const player = (playerRef.current = videojs(videoElement, options, () => {
console.log("player is ready");
onReady && onReady(player);
}));
} else {
// you can update player here [update player through props]
}
}, [options, onReady]);
return (
<div
data-vjs-player
style={{
paddingX: "15px",
// backgroundColor: "white",
}}
>
<video
ref={videoRef}
className="video-js vjs-big-play-centered"
width={"250px"}
height={"450px"}
/>
</div>
);
};
export default VideoJS;
本文标签: Safari snap issue with scrollSnapType quoty mandatoryquot using reactwindowStack Overflow
版权声明:本文标题:Safari snap issue with scrollSnapType: "y mandatory" using react-window - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736658269a1946312.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论