UNPKG

kinetic-slider

Version:

A WebGL-powered kinetic slider component using PIXI.js

180 lines (177 loc) 7.05 kB
import { useRef, useCallback, useEffect } from 'react'; // Development environment check const isDevelopment = "production" === 'development'; // Default debounce time const DEFAULT_DEBOUNCE_TIME = 100; /** * Hook to handle resize events for the slider * Ensures proper scaling and positioning of all visual elements when the window resizes */ const useResizeHandler = ({ sliderRef, appRef, slidesRef, textContainersRef, backgroundDisplacementSpriteRef, cursorDisplacementSpriteRef, resourceManager, debounceTime = DEFAULT_DEBOUNCE_TIME }) => { // Cancellation flag to prevent race conditions const cancellationRef = useRef({ isCancelled: false }); // Store debounce timer const resizeTimerRef = useRef(null); /** * Calculate sprite scale based on dimensions with improved error handling */ const calculateSpriteScale = useCallback((sprite, containerWidth, containerHeight) => { try { // Validate texture and dimensions if (!sprite.texture || !sprite.texture.width || !sprite.texture.height) { if (isDevelopment) ; return false; } const imageWidth = sprite.texture.width; const imageHeight = sprite.texture.height; // Skip invalid container dimensions if (!containerWidth || !containerHeight) { if (isDevelopment) ; return false; } // Calculate scale based on aspect ratios const imageAspect = imageWidth / imageHeight; const containerAspect = containerWidth / containerHeight; const scale = imageAspect > containerAspect ? containerHeight / imageHeight : containerWidth / imageWidth; // Apply scale and center sprite sprite.scale.set(scale); // Store base scale for future reference sprite.baseScale = scale; // Center the sprite sprite.x = containerWidth / 2; sprite.y = containerHeight / 2; // Track with ResourceManager if (resourceManager) { resourceManager.trackDisplayObject(sprite); } return true; } catch (error) { return false; } }, [resourceManager]); /** * Center a container within the slider */ const centerContainer = useCallback((container, width, height) => { try { container.x = width / 2; container.y = height / 2; // Track the updated container with ResourceManager if (resourceManager) { resourceManager.trackDisplayObject(container); } } catch (error) { } }, [resourceManager]); /** * Main resize handler function with comprehensive error handling */ const handleResize = useCallback(() => { // Reset cancellation flag cancellationRef.current.isCancelled = false; // Validate essential references if (!sliderRef.current || !appRef.current) { return; } try { const app = appRef.current; const containerWidth = sliderRef.current.clientWidth; const containerHeight = sliderRef.current.clientHeight; if (isDevelopment) ; // Clear any existing resize timer if (resizeTimerRef.current !== null) { if (resourceManager) { resourceManager.clearTimeout(resizeTimerRef.current); } else { clearTimeout(resizeTimerRef.current); } resizeTimerRef.current = null; } // Debounced resize function const resizeFn = () => { // Check for cancellation if (cancellationRef.current.isCancelled) return; try { // Resize renderer app.renderer.resize(containerWidth, containerHeight); // Update slides slidesRef.current.forEach((sprite) => { calculateSpriteScale(sprite, containerWidth, containerHeight); }); // Update text containers textContainersRef.current.forEach((container) => { centerContainer(container, containerWidth, containerHeight); }); // Update displacement sprites if (backgroundDisplacementSpriteRef.current) { centerContainer(backgroundDisplacementSpriteRef.current, containerWidth, containerHeight); } if (cursorDisplacementSpriteRef.current) { centerContainer(cursorDisplacementSpriteRef.current, containerWidth, containerHeight); } if (isDevelopment) ; } catch (error) { if (isDevelopment) ; } }; // Set timeout using ResourceManager or window if (resourceManager) { resizeTimerRef.current = resourceManager.setTimeout(resizeFn, debounceTime); } else { // Use type assertion since browser's setTimeout returns number while Node's returns Timeout resizeTimerRef.current = window.setTimeout(resizeFn, debounceTime); } } catch (error) { } }, [ sliderRef, appRef, slidesRef, textContainersRef, backgroundDisplacementSpriteRef, cursorDisplacementSpriteRef, resourceManager, debounceTime, calculateSpriteScale, centerContainer ]); // Main effect for resize handling useEffect(() => { // Skip during server-side rendering if (typeof window === 'undefined') return; // Add resize event listener window.addEventListener("resize", handleResize); // Initial resize handleResize(); // Cleanup function return () => { // Set cancellation flag cancellationRef.current.isCancelled = true; // Remove resize listener window.removeEventListener("resize", handleResize); // Clear any pending resize timer if (resizeTimerRef.current !== null) { if (resourceManager) { resourceManager.clearTimeout(resizeTimerRef.current); } else { clearTimeout(resizeTimerRef.current); } resizeTimerRef.current = null; } }; }, [handleResize, resourceManager]); // No return value needed as this hook sets up the resize handler }; export { useResizeHandler as default }; //# sourceMappingURL=useResizeHandler.js.map