Improve carousel behavior for smoother video browsing
Implement an infinite scrolling carousel by duplicating video content and refining scroll logic for seamless navigation within video categories. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 2eb1084e-b728-4449-9231-f1665924c8d5 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/2eb1084e-b728-4449-9231-f1665924c8d5/QCN70f2
This commit is contained in:
parent
34effd491b
commit
87dea07bae
@ -136,38 +136,22 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) {
|
|||||||
const scrollIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
const scrollIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const [showLeftButton, setShowLeftButton] = useState(false);
|
const [showLeftButton, setShowLeftButton] = useState(false);
|
||||||
const [showRightButton, setShowRightButton] = useState(true);
|
const [showRightButton, setShowRightButton] = useState(true);
|
||||||
|
|
||||||
|
// Create infinite carousel by duplicating videos
|
||||||
|
const infiniteVideos = [...category.videos, ...category.videos, ...category.videos];
|
||||||
|
|
||||||
const scroll = (direction: 'left' | 'right') => {
|
const scroll = (direction: 'left' | 'right') => {
|
||||||
if (!scrollRef.current) return;
|
if (!scrollRef.current) return;
|
||||||
|
|
||||||
const container = scrollRef.current;
|
const container = scrollRef.current;
|
||||||
const currentScroll = container.scrollLeft;
|
|
||||||
const maxScroll = container.scrollWidth - container.clientWidth;
|
|
||||||
const videoWidth = 224; // approx width of one video card + spacing
|
const videoWidth = 224; // approx width of one video card + spacing
|
||||||
const scrollAmount = videoWidth * 3; // Show 3 videos at a time
|
const scrollAmount = videoWidth * 2; // Show 2 videos at a time
|
||||||
|
|
||||||
let targetScroll;
|
|
||||||
|
|
||||||
if (direction === 'left') {
|
if (direction === 'left') {
|
||||||
if (currentScroll <= 10) {
|
container.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
|
||||||
// Jump to end for infinite loop
|
|
||||||
targetScroll = maxScroll;
|
|
||||||
} else {
|
|
||||||
targetScroll = currentScroll - scrollAmount;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (currentScroll >= maxScroll - 10) {
|
container.scrollBy({ left: scrollAmount, behavior: 'smooth' });
|
||||||
// Jump to beginning for infinite loop
|
|
||||||
targetScroll = 0;
|
|
||||||
} else {
|
|
||||||
targetScroll = currentScroll + scrollAmount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
container.scrollTo({
|
|
||||||
left: targetScroll,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const startAutoScroll = (direction: 'left' | 'right') => {
|
const startAutoScroll = (direction: 'left' | 'right') => {
|
||||||
@ -176,14 +160,36 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const checkScrollPosition = () => {
|
const checkScrollPosition = () => {
|
||||||
// Always show both buttons for infinite carousel
|
if (!scrollRef.current) return;
|
||||||
|
|
||||||
|
const container = scrollRef.current;
|
||||||
|
const currentScroll = container.scrollLeft;
|
||||||
|
const maxScroll = container.scrollWidth - container.clientWidth;
|
||||||
|
const sectionWidth = (container.scrollWidth / 3); // One third (original videos)
|
||||||
|
|
||||||
|
// Reset to middle section when approaching edges for infinite effect
|
||||||
|
if (currentScroll <= 100) {
|
||||||
|
// Jump to end of first section (start of second section)
|
||||||
|
container.scrollLeft = sectionWidth + currentScroll;
|
||||||
|
} else if (currentScroll >= maxScroll - 100) {
|
||||||
|
// Jump to start of second section
|
||||||
|
container.scrollLeft = sectionWidth + (currentScroll - 2 * sectionWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always show both buttons
|
||||||
setShowLeftButton(true);
|
setShowLeftButton(true);
|
||||||
setShowRightButton(true);
|
setShowRightButton(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check scroll position on mount and when videos change
|
// Initialize position to middle section on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
checkScrollPosition();
|
if (scrollRef.current && category.videos.length > 0) {
|
||||||
|
const container = scrollRef.current;
|
||||||
|
const sectionWidth = container.scrollWidth / 3;
|
||||||
|
container.scrollLeft = sectionWidth; // Start in middle section
|
||||||
|
setShowLeftButton(true);
|
||||||
|
setShowRightButton(true);
|
||||||
|
}
|
||||||
}, [category.videos]);
|
}, [category.videos]);
|
||||||
|
|
||||||
const stopAutoScroll = () => {
|
const stopAutoScroll = () => {
|
||||||
@ -290,8 +296,8 @@ function CategoryRow({ category, onVideoClick }: CategoryRowProps) {
|
|||||||
WebkitOverflowScrolling: 'touch'
|
WebkitOverflowScrolling: 'touch'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{category.videos.map((video, index) => (
|
{infiniteVideos.map((video, index) => (
|
||||||
<div key={video.id} className="flex-shrink-0 w-28 md:w-52 relative group">
|
<div key={`${video.id}-${index}`} className="flex-shrink-0 w-28 md:w-52 relative group">
|
||||||
{/* Top 10 Number overlay for first category */}
|
{/* Top 10 Number overlay for first category */}
|
||||||
{category.title.includes("Top 10") && index < 10 && (
|
{category.title.includes("Top 10") && index < 10 && (
|
||||||
<div className="absolute top-1 left-1 z-20 text-white font-black text-3xl md:text-5xl drop-shadow-2xl"
|
<div className="absolute top-1 left-1 z-20 text-white font-black text-3xl md:text-5xl drop-shadow-2xl"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user