UNPKG

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

73 lines (63 loc) 2.63 kB
/* This file was generated by https://github.com/pmndrs/gltfjsx and then customized manually. It uses drei's new useAnimations hook which extracts all actions and sets up a THREE.AnimationMixer for it so that you don't have to. All of the assets actions, action-names and clips are available in its output. */ import React, { useEffect, useState } from 'react' import { useGLTF, useTexture, useAnimations } from '@react-three/drei' import { a, useSpring } from '@react-spring/three' export default function Model(props) { // Fetch model and a separate texture const { nodes, animations } = useGLTF('/assets/examples/stacy.glb') const texture = useTexture('/assets/examples/stacy.jpg') // Extract animation actions const { ref, actions, names } = useAnimations(animations) // Hover and animation-index states const [hovered, setHovered] = useState(false) const [index, setIndex] = useState(4) // Animate the selection halo const { color, scale } = useSpring({ scale: hovered ? [1.15, 1.15, 1] : [1, 1, 1], color: hovered ? '#ff6d6d' : '#569AFF', }) // Change cursor on hover-state useEffect(() => void (document.body.style.cursor = hovered ? 'pointer' : 'auto'), [hovered]) // Change animation when the index changes useEffect(() => { // Reset and fade in animation after an index has been changed actions[names[index]].reset().fadeIn(0.5).play() // In the clean-up phase, fade it out // (page route may have changed) if (actions[names[index]]) { return () => actions[names[index]].fadeOut(0.5) } return null }, [index, actions, names]) return ( <group ref={ref} {...props} dispose={null}> <group rotation={[Math.PI / 2, 0, 0]} scale={0.01}> {/* actions */} <primitive object={nodes.mixamorigHips} /> {/* model */} <skinnedMesh castShadow receiveShadow onPointerOver={() => setHovered(true)} onPointerOut={() => setHovered(false)} onClick={() => setIndex((index + 1) % names.length)} geometry={nodes.stacy.geometry} skeleton={nodes.stacy.skeleton} rotation={[-Math.PI / 2, 0, 0]} scale={100}> <meshStandardMaterial map={texture} map-flipY={false} skinning /> </skinnedMesh> </group> {/* background circle */} {/* <a.mesh receiveShadow position={[0, 1, -1]} scale={scale}> <circleGeometry args={[1, 64]} /> <a.meshStandardMaterial color={color} /> </a.mesh> */} </group> ) }