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
69 lines (58 loc) • 2.34 kB
JSX
'use client'
import { useGLTF } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
import * as THREE from 'three'
import { useMemo, useRef, useState } from 'react'
import { Line, useCursor, MeshDistortMaterial } from '@react-three/drei'
import { useRouter } from 'next/navigation'
export const Blob = ({ route = '/', ...props }) => {
const router = useRouter()
const [hovered, hover] = useState(false)
useCursor(hovered)
return (
<mesh
onClick={() => router.push(route)}
onPointerOver={() => hover(true)}
onPointerOut={() => hover(false)}
{...props}>
<sphereGeometry args={[1, 64, 64]} />
<MeshDistortMaterial roughness={0.5} color={hovered ? 'hotpink' : '#1fb2f5'} />
</mesh>
)
}
export const Logo = ({ route = '/blob', ...props }) => {
const mesh = useRef(null)
const router = useRouter()
const [hovered, hover] = useState(false)
const points = useMemo(() => new THREE.EllipseCurve(0, 0, 3, 1.15, 0, 2 * Math.PI, false, 0).getPoints(100), [])
useCursor(hovered)
useFrame((state, delta) => {
const t = state.clock.getElapsedTime()
mesh.current.rotation.y = Math.sin(t) * (Math.PI / 8)
mesh.current.rotation.x = Math.cos(t) * (Math.PI / 8)
mesh.current.rotation.z -= delta / 4
})
return (
<group ref={mesh} {...props}>
{/* @ts-ignore */}
<Line worldUnits points={points} color='#1fb2f5' lineWidth={0.15} />
{/* @ts-ignore */}
<Line worldUnits points={points} color='#1fb2f5' lineWidth={0.15} rotation={[0, 0, 1]} />
{/* @ts-ignore */}
<Line worldUnits points={points} color='#1fb2f5' lineWidth={0.15} rotation={[0, 0, -1]} />
<mesh onClick={() => router.push(route)} onPointerOver={() => hover(true)} onPointerOut={() => hover(false)}>
<sphereGeometry args={[0.55, 64, 64]} />
<meshPhysicalMaterial roughness={0.5} color={hovered ? 'hotpink' : '#1fb2f5'} />
</mesh>
</group>
)
}
export function Duck(props) {
const { scene } = useGLTF('/duck.glb')
useFrame((state, delta) => (scene.rotation.y += delta))
return <primitive object={scene} {...props} />
}
export function Dog(props) {
const { scene } = useGLTF('/dog.glb')
return <primitive object={scene} {...props} />
}