diff --git a/src/hooks/useSmoothTransitionColor.tsx b/src/hooks/useSmoothTransitionColor.tsx new file mode 100644 index 0000000..a92a33c --- /dev/null +++ b/src/hooks/useSmoothTransitionColor.tsx @@ -0,0 +1,25 @@ +import { useRef } from 'react'; + +import { useFrame } from '@react-three/fiber'; +import { Color, MeshStandardMaterial } from 'three'; + +const TRANSITION_SPEED = 5; + +export const useSmoothTransitionColor = ({ + color, + initialMaterial = new MeshStandardMaterial(), +}: { + color: string | Color; + initialMaterial?: MeshStandardMaterial; +}): MeshStandardMaterial => { + const materialRef = useRef(initialMaterial); + + useFrame((_, delta) => { + if (materialRef.current) { + const targetColor = new Color(color); + materialRef.current.color.lerp(targetColor, delta * TRANSITION_SPEED); // Smooth transition + } + }); + + return materialRef.current ?? initialMaterial; +}; diff --git a/src/modules/models/FirTree/useFirTree.tsx b/src/modules/models/FirTree/useFirTree.tsx index c6ec5e8..ce96620 100644 --- a/src/modules/models/FirTree/useFirTree.tsx +++ b/src/modules/models/FirTree/useFirTree.tsx @@ -4,6 +4,7 @@ import { GLTF } from 'three-stdlib'; import { MODELS_3D_ROOT_PATH } from '@/config/models'; import { useSeason } from '@/context/SeasonContext'; +import { useSmoothTransitionColor } from '@/hooks/useSmoothTransitionColor'; import { Seasons } from '@/types/seasons'; import { fromRGB } from '@/utils/colors'; @@ -39,8 +40,10 @@ type UseFirTree = { export const useFirTree = (): UseFirTree => { const { season } = useSeason(); const { nodes, materials } = useGLTF(GLB_FILE_PATH) as GLTFResult; - const spineMaterial = new MeshStandardMaterial().copy(materials.Spine); - spineMaterial.color = COLORS_BY_SEASON[season]; + const spineMaterial = useSmoothTransitionColor({ + color: COLORS_BY_SEASON[season], + initialMaterial: materials.Spine, + }); return { nodes, diff --git a/src/modules/models/Garden.tsx b/src/modules/models/Garden.tsx index b7d34d9..6b01933 100644 --- a/src/modules/models/Garden.tsx +++ b/src/modules/models/Garden.tsx @@ -2,6 +2,7 @@ import { RoundedBox } from '@react-three/drei'; import { Vector3 } from '@react-three/fiber'; import { useSeason } from '@/context/SeasonContext'; +import { useSmoothTransitionColor } from '@/hooks/useSmoothTransitionColor'; import { Seasons } from '@/types/seasons'; const COLORS_BY_SEASON = { @@ -20,13 +21,15 @@ type Props = { export const Garden = ({ position }: Props): JSX.Element => { const { season } = useSeason(); + const materialRef = useSmoothTransitionColor({ + color: COLORS_BY_SEASON[season], + }); return ( - - + material={materialRef} + /> ); }; diff --git a/src/modules/models/Tree/useTree.tsx b/src/modules/models/Tree/useTree.tsx index f030645..5d50ec4 100644 --- a/src/modules/models/Tree/useTree.tsx +++ b/src/modules/models/Tree/useTree.tsx @@ -4,6 +4,7 @@ import { GLTF } from 'three-stdlib'; import { MODELS_3D_ROOT_PATH } from '@/config/models'; import { useSeason } from '@/context/SeasonContext'; +import { useSmoothTransitionColor } from '@/hooks/useSmoothTransitionColor'; import { Season, Seasons } from '@/types/seasons'; import { fromRGB } from '@/utils/colors'; @@ -40,8 +41,10 @@ type UseTree = { export const useTree = (): UseTree => { const { season } = useSeason(); const { nodes, materials } = useGLTF(GLB_FILE_PATH) as GLTFResult; - const leafMaterial = new MeshStandardMaterial().copy(materials.Leaf); - leafMaterial.color = COLORS_BY_SEASON[season]; + const leafMaterial = useSmoothTransitionColor({ + color: COLORS_BY_SEASON[season], + initialMaterial: materials.Leaf, + }); return { season,