import React, { useState, useEffect, useRef } from 'react'; import '../styles/reel.css'; import gameconfig from '../../gameconfig'; import { mediaUrl } from '../utils/axiosInstance'; interface SlotImage { id: number; image_path: string; section_number: number; } interface ReelProps { slotImages: SlotImage[]; isSpinning: boolean; spinDuration?: number; onSpinComplete?: () => void; targetId?: number; // The section_number } const Reel: React.FC<ReelProps> = ({ slotImages, isSpinning, spinDuration = 2000, onSpinComplete, targetId = -1, }) => { const reelRef = useRef<HTMLDivElement>(null); const [spinning, setSpinning] = useState(false); const [displaySequence, setDisplaySequence] = useState<SlotImage[]>([]); useEffect(() => { document.documentElement.style.setProperty('--reel-border-color', gameconfig.reelBorder); }, []); // Generate a sequence with the target image centered in the viewport useEffect(() => { if (slotImages.length === 0) return; // Find the target image by section_number const targetImage = slotImages.find((img) => img.section_number === targetId) || slotImages[0]; const otherImages = slotImages.filter( (img) => img.section_number !== targetImage.section_number, ); // Function to get random image const getRandomImage = () => { const randomIndex = Math.floor(Math.random() * otherImages.length); return otherImages[randomIndex] || slotImages[0]; // Fallback to first image }; // Calculate viewport properties const imageHeight = 113; const viewportHeight = 339; const imagesInViewport = Math.ceil(viewportHeight / imageHeight); // 3 images const centerIndexInViewport = Math.floor(imagesInViewport / 2); // 1 // Create a much longer sequence for continuous spinning const totalImages = 80; // more images for continuous spinning const sequence: SlotImage[] = []; // Fill sequence with random images before the target for (let i = 0; i < totalImages / 2 - centerIndexInViewport; i++) { sequence.push(getRandomImage()); } // Add the target image at the center position sequence.push(targetImage); // Fill sequence with random images after the target for (let i = sequence.length; i < totalImages; i++) { sequence.push(getRandomImage()); } setDisplaySequence(sequence); }, [slotImages, targetId]); useEffect(() => { const reel = reelRef.current; if (!reel || displaySequence.length === 0) return; if (isSpinning && !spinning) { setSpinning(true); const imageHeight = 113; const viewportHeight = 339; const imagesInViewport = Math.ceil(viewportHeight / imageHeight); // 3 const centerIndexInViewport = Math.floor(imagesInViewport / 2); // 1 // Find the index of the target image in the sequence const targetIndex = displaySequence.findIndex((img) => img.section_number === targetId); if (targetIndex === -1) { console.error(`Target image with section_number ${targetId} not found in sequence`); return; } // Calculate stop position so target is centered in viewport const stopPosition = -(targetIndex - centerIndexInViewport) * imageHeight; console.log( `Reel Stop Position: ${stopPosition}px for targetId (section_number): ${targetId}`, ); // Reset the reel position reel.style.transition = 'none'; reel.style.transform = 'translateY(0)'; void reel.offsetHeight; // Force reflow const normalSpeedPhase = spinDuration * 0.5; //normal const decelerationPhase = spinDuration * 1.0; //gradually slow const spinDistance = displaySequence.length * imageHeight; const midwayPosition = spinDistance * 0.5; reel.style.transition = `transform ${normalSpeedPhase}ms linear`; reel.style.transform = `translateY(-${midwayPosition}px)`; setTimeout(() => { reel.style.transition = `transform ${decelerationPhase}ms cubic-bezier(0.05, 0, 0.2, 1)`; reel.style.transform = `translateY(${stopPosition}px)`; }, normalSpeedPhase); // Animation complete setTimeout(() => { setSpinning(false); if (onSpinComplete) onSpinComplete(); }, spinDuration); } }, [isSpinning, spinning, spinDuration, displaySequence, slotImages, targetId, onSpinComplete]); return ( <div className="reel-frames"> <div className={`reels-machinery ${spinning ? 'spinning' : ''}`} style={{ border: `4px solid ${gameconfig.reelBorder}` }} > <div className="reel-viewport"> <div className="reel" ref={reelRef}> {displaySequence.map((image, index) => ( <div className="figures" key={`${image.id}-${index}`}> <img className="slot-image" style={{ color: 'white' }} src={`${mediaUrl}/${image.image_path}`} alt={`imageno-> ${image.section_number},ID-> ${image.id}`} /> </div> ))} </div> </div> </div> </div> ); }; export default Reel;