threed-garden
Version:
ThreeD Garden: WebGL 3D Environment Interface for Next.JS React TypeScript Three.JS React-Three Physics, 2D Paper.JS; APIs: Apollo GraphQL, WordPress; CSS: Tailwind, Radix-UI; Libraries: FarmBot 3D; AI: OpenAI, DeepSeek
56 lines (48 loc) • 1.93 kB
JSX
import React, { useState, useCallback } from 'react'
import { useSpring } from 'react-spring'
import { usePrefersReducedMotion } from './usePrefersReducedMotion'
// Heavily inspired by Josh Comeau: https://www.joshwcomeau.com/react/boop/ 💖
// Wiggle function accepts various parameters specifying properties for the animation
export function useWiggle({
x = 0,
y = 0,
rotation = 0,
scale = 1,
timing = 150,
springConfig = {
tension: 300,
friction: 10,
},
}) {
// Accessibility setting from the user system indicating that they prefer to minimize motion
const prefersReducedMotion = usePrefersReducedMotion()
// Declare state variable isActive, set initially to false
const [isActive, setIsActive] = useState(false)
// We offload the actual animation to spring: https://www.react-spring.io/docs/hooks/use-spring
const style = useSpring({
transform: isActive
? `translate(${x}px, ${y}px) rotate(${rotation}deg) scale(${scale})`
: `translate(0px, 0px) rotate(0deg) scale(1)`,
config: springConfig,
})
// Timing parameter determines how long the wiggle lasts using browser setTimeout function
// React useEffect function https://reactjs.org/docs/hooks-effect.html
React.useEffect(() => {
if (!isActive) {
return
}
const timeoutId = window.setTimeout(() => {
setIsActive(false)
}, timing)
return () => {
window.clearTimeout(timeoutId)
}
}, [isActive]) // Continue wiggle until isActive is set false when timeout elapses
// Set wiggle to active when the triggering event occurs - will be set false when effect completes above
const trigger = useCallback(() => {
setIsActive(true)
}, [])
let appliedStyle = prefersReducedMotion ? {} : style
// Return animation style effect and function to apply on trigger in page
return [appliedStyle, trigger]
}