From d235d6955ae31ca7c604ec4f58d88f25a287796b Mon Sep 17 00:00:00 2001 From: DefectingCat Date: Thu, 14 Sep 2023 16:14:22 +0800 Subject: [PATCH] add model animation play --- components/models/cloud-model.tsx | 40 +++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/components/models/cloud-model.tsx b/components/models/cloud-model.tsx index 572a51e..d61f579 100644 --- a/components/models/cloud-model.tsx +++ b/components/models/cloud-model.tsx @@ -1,8 +1,15 @@ -import { useLoader } from '@react-three/fiber'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { useFrame, useLoader, useThree } from '@react-three/fiber'; +import { getMousePosition } from 'lib/utils'; +import { useEffect, useRef } from 'react'; +import * as THREE from 'three'; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; +import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; +import { rotationX, rotationY } from './home-model'; const CloudModel = () => { + const mixer = useRef(null); + + const camera = useThree((state) => state.camera); const gltf = useLoader( GLTFLoader, './models/cloud_station/modelDraco.gltf', @@ -12,6 +19,35 @@ const CloudModel = () => { loader.setDRACOLoader(dracoLoader); }, ); + useEffect(() => { + mixer.current = new THREE.AnimationMixer(gltf.scene); + gltf.animations.forEach((clip) => { + mixer.current?.clipAction(clip).play(); + }); + + const halfWidth = Math.floor(window.innerWidth / 2); + const halfHeight = Math.floor(window.innerHeight / 2); + + const moveHandler = (e: MouseEvent | globalThis.TouchEvent) => { + const { x, y } = getMousePosition(e); + // > 0 is right, < 0 is left + // if (directionX > 0) root.rotation.y += 0.01; + gltf.scene.rotation.x = rotationX * ((y - halfHeight) / halfHeight); + gltf.scene.rotation.y = rotationY * ((x - halfWidth) / halfWidth); + }; + window.addEventListener('mousemove', moveHandler); + window.addEventListener('touchmove', moveHandler); + + return () => { + window.removeEventListener('mousemove', moveHandler); + window.removeEventListener('touchmove', moveHandler); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useFrame((_, delta) => { + mixer.current?.update(delta); + }); return ( <>