UNPKG

kinetic-slider

Version:

A WebGL-powered kinetic slider component using PIXI.js

1 lines 33.4 kB
{"version":3,"file":"useMouseTracking.cjs","sources":["../../../src/hooks/useMouseTracking.ts"],"sourcesContent":["import { useEffect, useRef, useCallback, type RefObject } from 'react';\nimport { Sprite, DisplacementFilter } from 'pixi.js';\nimport { gsap } from 'gsap';\nimport ResourceManager from '../managers/ResourceManager';\nimport RenderScheduler from '../managers/RenderScheduler';\nimport { UpdateType } from '../managers/UpdateTypes';\n\n// Development environment check\nconst isDevelopment = import.meta.env?.MODE === 'development';\n\n// Define a custom event for filter coordination\nconst FILTER_COORDINATION_EVENT = 'kinetic-slider:filter-update';\n\ninterface UseMouseTrackingProps {\n sliderRef: RefObject<HTMLDivElement | null>;\n backgroundDisplacementSpriteRef: RefObject<Sprite | null>;\n cursorDisplacementSpriteRef: RefObject<Sprite | null>;\n backgroundDisplacementFilterRef?: RefObject<DisplacementFilter | null>;\n cursorDisplacementFilterRef?: RefObject<DisplacementFilter | null>;\n cursorImgEffect: boolean;\n cursorMomentum: number;\n resourceManager?: ResourceManager | null;\n}\n\n// Interface for filter update event detail\ninterface FilterUpdateEventDetail {\n filterId: string;\n intensity: number;\n timestamp: number;\n source: 'mouse-tracking';\n}\n\n/**\n * Hook to handle mouse movement tracking for displacement sprites\n * Refactored to use RenderScheduler for batched updates\n */\nconst useMouseTracking = ({\n sliderRef,\n backgroundDisplacementSpriteRef,\n cursorDisplacementSpriteRef,\n backgroundDisplacementFilterRef,\n cursorDisplacementFilterRef,\n cursorImgEffect,\n cursorMomentum,\n resourceManager\n }: UseMouseTrackingProps) => {\n // Track active animations for batch processing\n const activeAnimationsRef = useRef<gsap.core.Tween[]>([]);\n\n // Track component mount state\n const isMountedRef = useRef(true);\n\n // Track throttling state\n const throttleStateRef = useRef({\n lastThrottleTime: 0,\n throttleDelay: 16 // ~60fps\n });\n\n // Track debouncing state for non-critical updates\n const debounceStateRef = useRef({\n debounceTimerId: 0,\n debounceDelay: 100, // 100ms debounce for non-critical updates\n lastDebounceTime: 0,\n pendingUpdate: false\n });\n\n // Track last mouse position for use by scheduled updates\n const lastMousePositionRef = useRef({\n x: 0,\n y: 0,\n containerRect: null as DOMRect | null,\n intensity: 0, // Store calculated intensity for reuse\n timestamp: 0 // When this position was recorded\n });\n\n // Get the scheduler instance\n const scheduler = RenderScheduler.getInstance();\n\n // Process batch animations through ResourceManager\n const processBatchAnimations = useCallback(() => {\n try {\n const animations = activeAnimationsRef.current;\n\n // Skip if no ResourceManager or no animations\n if (!resourceManager || animations.length === 0) return;\n\n // Track animations in batch\n resourceManager.trackAnimationBatch(animations);\n\n // Clear array by setting length to 0 (more efficient than creating new array)\n animations.length = 0;\n\n if (isDevelopment) {\n console.log('Processed batch animations for mouse tracking');\n }\n } catch (error) {\n if (isDevelopment) {\n console.error('Error processing batch animations:', error);\n }\n // Clear array even on error to avoid stuck state\n activeAnimationsRef.current = [];\n }\n }, [resourceManager]);\n\n // Clean up active animations\n const cleanupAnimations = useCallback(() => {\n try {\n const animations = activeAnimationsRef.current;\n\n // Kill all animations\n animations.forEach(tween => {\n if (tween && tween.isActive()) {\n tween.kill();\n }\n });\n\n // Clear array\n animations.length = 0;\n } catch (error) {\n if (isDevelopment) {\n console.error('Error cleaning up animations:', error);\n }\n // Reset array even on error\n activeAnimationsRef.current = [];\n }\n }, []);\n\n // Calculate displacement intensity based on mouse position\n const calculateDisplacementIntensity = useCallback((\n mouseX: number,\n mouseY: number,\n rect: DOMRect\n ): number => {\n try {\n // Calculate center point and distance\n const centerX = rect.width / 2;\n const centerY = rect.height / 2;\n const distanceFromCenter = Math.sqrt(\n Math.pow(mouseX - centerX, 2) +\n Math.pow(mouseY - centerY, 2)\n );\n\n // Calculate maximum possible distance\n const maxDistance = Math.sqrt(\n Math.pow(rect.width / 2, 2) +\n Math.pow(rect.height / 2, 2)\n );\n\n // Normalize intensity (0-1 range)\n return Math.min(1, distanceFromCenter / (maxDistance * 0.7));\n } catch (error) {\n if (isDevelopment) {\n console.error('Error calculating displacement intensity:', error);\n }\n // Return safe default value on error\n return 0.5;\n }\n }, []);\n\n /**\n * Dispatch a custom event to coordinate with the filter system\n * This allows for better integration with the filter batching system\n * @param filterId The ID of the filter to update\n * @param intensity The intensity value to set\n * @param priority Optional priority level for the update (defaults to 'high')\n */\n const dispatchFilterUpdate = useCallback((filterId: string, intensity: number, priority: 'normal' | 'high' | 'critical' = 'high') => {\n try {\n if (typeof window === 'undefined') return;\n\n const detail = {\n type: filterId,\n intensity,\n timestamp: Date.now(),\n source: 'mouse-tracking',\n priority\n };\n\n const event = new CustomEvent(FILTER_COORDINATION_EVENT, { detail });\n window.dispatchEvent(event);\n\n if (isDevelopment) {\n console.log(`Dispatched filter update for ${filterId} with intensity ${intensity} (priority: ${priority})`);\n }\n } catch (error) {\n if (isDevelopment) {\n console.error('Error dispatching filter update:', error);\n }\n }\n }, []);\n\n /**\n * Animation function that gets scheduled by the RenderScheduler\n * Creates and applies animations for mouse tracking displacement\n */\n const animateDisplacementScheduled = useCallback(() => {\n try {\n if (!isMountedRef.current) return;\n\n // Get stored mouse position\n const { x: mouseX, y: mouseY, containerRect, intensity: storedIntensity } = lastMousePositionRef.current;\n\n if (!containerRect) return;\n\n // Use stored intensity if available, otherwise calculate it\n const displacementIntensity = storedIntensity || calculateDisplacementIntensity(mouseX, mouseY, containerRect);\n\n // Get current refs\n const backgroundSprite = backgroundDisplacementSpriteRef.current;\n const cursorSprite = cursorDisplacementSpriteRef.current;\n const bgFilter = backgroundDisplacementFilterRef?.current;\n const cursorFilter = cursorDisplacementFilterRef?.current;\n\n if (isDevelopment) {\n console.log('Animating displacement with intensity:', displacementIntensity, {\n hasBgSprite: !!backgroundSprite,\n hasCursorSprite: !!cursorSprite,\n hasBgFilter: !!bgFilter,\n hasCursorFilter: !!cursorFilter,\n bgFilterScale: bgFilter ? { x: bgFilter.scale.x, y: bgFilter.scale.y } : 'no filter',\n cursorFilterScale: cursorFilter ? { x: cursorFilter.scale.x, y: cursorFilter.scale.y } : 'no filter'\n });\n }\n\n // Clear existing animations\n cleanupAnimations();\n\n // Collect new animations\n const newAnimations: gsap.core.Tween[] = [];\n\n // Animate background displacement sprite\n if (backgroundSprite) {\n // Apply immediate position update for instant visibility\n backgroundSprite.x = mouseX;\n backgroundSprite.y = mouseY;\n\n const bgSpriteTween = gsap.to(backgroundSprite, {\n x: mouseX,\n y: mouseY,\n duration: cursorMomentum,\n ease: 'power2.out'\n });\n\n newAnimations.push(bgSpriteTween);\n\n // Animate background filter scale if available\n if (bgFilter) {\n const intensity = displacementIntensity * 30;\n\n // Ensure the filter is visible by applying immediate scale\n if (bgFilter.scale.x === 0 || bgFilter.scale.y === 0 || bgFilter.scale.x < intensity) {\n if (isDevelopment) {\n console.log(`Background filter was inactive or too small (${bgFilter.scale.x}, ${bgFilter.scale.y}), setting to ${intensity}`);\n }\n bgFilter.scale.x = intensity;\n bgFilter.scale.y = intensity;\n }\n\n // Dispatch filter update event for coordination with filter system\n dispatchFilterUpdate('background-displacement', intensity, 'critical');\n\n const bgFilterTween = gsap.to(bgFilter.scale, {\n x: intensity,\n y: intensity,\n duration: cursorMomentum,\n ease: 'power2.out'\n });\n\n newAnimations.push(bgFilterTween);\n }\n }\n\n // Animate cursor displacement sprite if effect is enabled\n if (cursorImgEffect && cursorSprite) {\n // Apply immediate position update for instant visibility\n cursorSprite.x = mouseX;\n cursorSprite.y = mouseY;\n\n const cursorSpriteTween = gsap.to(cursorSprite, {\n x: mouseX,\n y: mouseY,\n duration: cursorMomentum,\n ease: 'power2.out'\n });\n\n newAnimations.push(cursorSpriteTween);\n\n // Animate cursor filter scale if available\n if (cursorFilter) {\n const intensity = displacementIntensity * 15;\n\n // Ensure the filter is visible by applying immediate scale\n if (cursorFilter.scale.x === 0 || cursorFilter.scale.y === 0 || cursorFilter.scale.x < intensity) {\n if (isDevelopment) {\n console.log(`Cursor filter was inactive or too small (${cursorFilter.scale.x}, ${cursorFilter.scale.y}), setting to ${intensity}`);\n }\n cursorFilter.scale.x = intensity;\n cursorFilter.scale.y = intensity;\n }\n\n // Dispatch filter update event for coordination with filter system\n dispatchFilterUpdate('cursor-displacement', intensity, 'critical');\n\n const cursorFilterTween = gsap.to(cursorFilter.scale, {\n x: intensity,\n y: intensity,\n duration: cursorMomentum,\n ease: 'power2.out'\n });\n\n newAnimations.push(cursorFilterTween);\n }\n }\n\n // Add new animations to active animations ref\n activeAnimationsRef.current.push(...newAnimations);\n\n // Process animations in batch\n processBatchAnimations();\n\n // Schedule an immediate render update to ensure changes are visible\n scheduler.scheduleTypedUpdate(\n 'mouseTracking',\n UpdateType.DISPLACEMENT_EFFECT,\n () => {\n if (isDevelopment) {\n console.log('Immediate render update for displacement effect');\n }\n },\n 'high'\n );\n\n // Reset pending update flag after processing\n debounceStateRef.current.pendingUpdate = false;\n } catch (error) {\n if (isDevelopment) {\n console.error('Error animating displacement:', error);\n }\n // Reset pending update flag even on error\n debounceStateRef.current.pendingUpdate = false;\n }\n }, [\n backgroundDisplacementSpriteRef,\n cursorDisplacementSpriteRef,\n backgroundDisplacementFilterRef,\n cursorDisplacementFilterRef,\n cursorImgEffect,\n cursorMomentum,\n cleanupAnimations,\n processBatchAnimations,\n calculateDisplacementIntensity,\n dispatchFilterUpdate,\n scheduler\n ]);\n\n /**\n * Debounced version of displacement animation for non-critical updates\n * This is used when mouse movements are rapid but don't need immediate visual feedback\n */\n const debouncedDisplacementUpdate = useCallback(() => {\n try {\n if (!isMountedRef.current) return;\n\n // Clear any existing debounce timer\n if (debounceStateRef.current.debounceTimerId) {\n window.clearTimeout(debounceStateRef.current.debounceTimerId);\n }\n\n // Set a new debounce timer\n debounceStateRef.current.debounceTimerId = window.setTimeout(() => {\n // Only schedule if we have a pending update\n if (debounceStateRef.current.pendingUpdate) {\n scheduler.scheduleTypedUpdate(\n 'mouseTracking',\n UpdateType.FILTER_UPDATE, // Lower priority than direct mouse response\n animateDisplacementScheduled,\n 'debounced'\n );\n }\n }, debounceStateRef.current.debounceDelay);\n } catch (error) {\n if (isDevelopment) {\n console.error('Error in debounced update:', error);\n }\n }\n }, [animateDisplacementScheduled, scheduler]);\n\n /**\n * Handle mouse movement inside the slider\n */\n const handleMouseMove = useCallback((event: Event) => {\n try {\n if (!isMountedRef.current) return;\n\n // Cast to MouseEvent for accessing mouse-specific properties\n const mouseEvent = event as MouseEvent;\n\n // Get current slider element\n const slider = sliderRef.current;\n if (!slider) return;\n\n // Get bounding rect\n const rect = slider.getBoundingClientRect();\n\n // Calculate mouse position relative to slider\n const mouseX = mouseEvent.clientX - rect.left;\n const mouseY = mouseEvent.clientY - rect.top;\n\n // Store mouse position for use by scheduled updates\n const lastPosition = lastMousePositionRef.current;\n lastPosition.x = mouseX;\n lastPosition.y = mouseY;\n lastPosition.containerRect = rect;\n lastPosition.timestamp = Date.now();\n\n // Calculate displacement intensity only once and store it\n lastPosition.intensity = calculateDisplacementIntensity(mouseX, mouseY, rect);\n\n // Throttling for performance optimization\n const now = Date.now();\n const { lastThrottleTime, throttleDelay } = throttleStateRef.current;\n\n if (now - lastThrottleTime < throttleDelay) {\n // Skip update if we're throttling\n return;\n }\n\n // Update throttle time\n throttleStateRef.current.lastThrottleTime = now;\n\n // Schedule the update with the render scheduler\n scheduler.scheduleTypedUpdate(\n 'mouseTracking',\n UpdateType.MOUSE_RESPONSE,\n animateDisplacementScheduled,\n 'high'\n );\n } catch (error) {\n if (isDevelopment) {\n console.error('Error handling mouse move:', error);\n }\n }\n }, [sliderRef, animateDisplacementScheduled, calculateDisplacementIntensity, scheduler]);\n\n /**\n * Handle mouse leave event - fade out displacement effects\n */\n const handleMouseLeave = useCallback(() => {\n try {\n if (!isMountedRef.current) return;\n\n if (isDevelopment) {\n console.log('[useMouseTracking] Mouse left slider - fading out displacement effects');\n }\n\n // Get current refs\n const backgroundSprite = backgroundDisplacementSpriteRef.current;\n const cursorSprite = cursorDisplacementSpriteRef.current;\n const bgFilter = backgroundDisplacementFilterRef?.current;\n const cursorFilter = cursorDisplacementFilterRef?.current;\n\n // Collect new animations\n const newAnimations: gsap.core.Tween[] = [];\n\n // Fade out background filter\n if (bgFilter) {\n const bgFilterTween = gsap.to(bgFilter.scale, {\n x: 0,\n y: 0,\n duration: 0.5,\n ease: \"power2.out\"\n });\n newAnimations.push(bgFilterTween);\n\n // Dispatch filter update event for coordination with filter system\n dispatchFilterUpdate('background-displacement', 0, 'high');\n }\n\n // Fade out cursor filter\n if (cursorFilter) {\n const cursorFilterTween = gsap.to(cursorFilter.scale, {\n x: 0,\n y: 0,\n duration: 0.5,\n ease: \"power2.out\"\n });\n newAnimations.push(cursorFilterTween);\n\n // Dispatch filter update event for coordination with filter system\n dispatchFilterUpdate('cursor-displacement', 0, 'high');\n }\n\n // Add new animations to active animations ref\n activeAnimationsRef.current.push(...newAnimations);\n\n // Process animations in batch\n processBatchAnimations();\n\n // Schedule an immediate render update\n scheduler.scheduleTypedUpdate(\n 'mouseTracking',\n UpdateType.DISPLACEMENT_EFFECT,\n () => {\n if (isDevelopment) {\n console.log('[useMouseTracking] Fade-out render update for mouse leave');\n }\n },\n 'high'\n );\n } catch (error) {\n if (isDevelopment) {\n console.error('[useMouseTracking] Error handling mouse leave:', error);\n }\n }\n }, [\n backgroundDisplacementFilterRef,\n cursorDisplacementFilterRef,\n backgroundDisplacementSpriteRef,\n cursorDisplacementSpriteRef,\n dispatchFilterUpdate,\n processBatchAnimations,\n scheduler\n ]);\n\n // Set up mouse tracking\n useEffect(() => {\n // Skip during server-side rendering\n if (typeof window === 'undefined') return;\n\n // Skip if slider reference is not available\n if (!sliderRef.current) return;\n\n // Reset mounted state\n isMountedRef.current = true;\n\n try {\n const node = sliderRef.current;\n\n // Register event listeners\n if (resourceManager) {\n // Batch registration with ResourceManager\n const listeners = new Map<string, EventCallback[]>();\n listeners.set('mousemove', [handleMouseMove]);\n listeners.set('mouseleave', [handleMouseLeave]); // Add mouseleave handler\n resourceManager.addEventListenerBatch(node, listeners);\n } else {\n // Direct registration\n node.addEventListener('mousemove', handleMouseMove, { passive: true });\n node.addEventListener('mouseleave', handleMouseLeave, { passive: true }); // Add mouseleave handler\n }\n\n // Cleanup on unmount\n return () => {\n // Update mounted state immediately\n isMountedRef.current = false;\n\n try {\n // Clean up animations\n cleanupAnimations();\n\n // Clear any debounce timer\n if (debounceStateRef.current.debounceTimerId) {\n window.clearTimeout(debounceStateRef.current.debounceTimerId);\n debounceStateRef.current.debounceTimerId = 0;\n }\n\n // Cancel any scheduled updates\n scheduler.cancelTypedUpdate('mouseTracking', UpdateType.MOUSE_RESPONSE);\n scheduler.cancelTypedUpdate('mouseTracking', UpdateType.FILTER_UPDATE, 'debounced');\n\n // ResourceManager handles its own cleanup\n if (!resourceManager) {\n node.removeEventListener('mousemove', handleMouseMove);\n node.removeEventListener('mouseleave', handleMouseLeave); // Remove mouseleave handler\n }\n } catch (cleanupError) {\n if (isDevelopment) {\n console.error('Error during mouse tracking cleanup:', cleanupError);\n }\n }\n };\n } catch (error) {\n if (isDevelopment) {\n console.error('Error setting up mouse tracking:', error);\n }\n // Return empty cleanup function\n return () => {};\n }\n }, [\n sliderRef,\n handleMouseMove,\n handleMouseLeave, // Add handleMouseLeave to dependencies\n cleanupAnimations,\n resourceManager,\n scheduler\n ]);\n};\n\n// Type definition for event callback - to match ResourceManager's expected type\ntype EventCallback = EventListenerOrEventListenerObject;\n\nexport default useMouseTracking;"],"names":["useRef","RenderScheduler","useCallback","gsap","UpdateType","useEffect"],"mappings":"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"}