"use client" import { Canvas, useFrame, useThree } from '@react-three/fiber' import { useHelper, OrbitControls, BakeShadows, SoftShadows, Sky, Environment, Lightformer, Outlines, Line, Cone, Text, Billboard } from '@react-three/drei' import { Leva, useControls } from 'leva' import { StrictMode, useEffect, useRef, useMemo, useLayoutEffect } from 'react' import * as THREE from 'three' export default function App() { return ( <StrictMode> <Leva flat /> <Canvas camera={{ fov: 50, near: 0.1, far: 200, position: [- 50, 50, 50] }} shadows> <Experience /> </Canvas> </StrictMode> ) } export function Experience() { const { start, end, thickness } = useControls('Geometry', { start: { value: [0, 0], step: 0.25 }, end: { value: [10, 10], step: 0.25 }, thickness: { value: 0.15, min: 0, max: 1 } }) return <> <OrbitControls makeDefault /> <directionalLight position={[1, 2, 3]} intensity={1.5} /> <ambientLight intensity={0.5} /> <Sky /> <Arrow color='black' thickness={thickness} start={[start[0], 0, start[1]]} end={[end[0], 0, end[1]]} /> <axesHelper /> <mesh rotation-x={- Math.PI * 0.5} scale={1}> <planeGeometry args={[10, 10, 1, 1]} /> <meshStandardMaterial color="greenyellow" /> </mesh> </> } export function Arrow({ start = [0, 0, 0], end = [20, 0, 0], color = 'black', thickness = 0.15, text = { content: 'Hello World', color: 'black', fontSize: 2, fontWeight: 'normal', fontStyle: 'normal', anchorY: 'bottom' }, ...props }) { const length = Math.sqrt((start[0] - end[0]) ** 2 + (start[1] - end[1]) ** 2 + (start[2] - end[2]) ** 2) const headLength = 10 * thickness const headWidth = 3 * thickness const end3 = useMemo(() => new THREE.Vector3(...end), [end]) const refgroup = useRef() useLayoutEffect(() => { refgroup.current.lookAt(end3) }, [end3]) return ( <group ref={refgroup} position={start} {...props}> <mesh position={[0, 0, (length - headLength) / 2]} scale={[thickness, length - headLength, thickness]} rotation-x={Math.PI / 2}> <cylinderGeometry args={[1, 1, 1, 12]} /> <meshBasicMaterial color={color} /> </mesh> <mesh position={[0, 0, length - headLength / 2]} scale={[headWidth, headLength, headWidth]} rotation-x={Math.PI / 2}> <coneGeometry args={[1, 1, 12]} /> <meshBasicMaterial color={color} /> </mesh> {text && <Billboard> <Text position={[0.5, 0, 0]} anchorX='left' {...text}>{text.content}</Text> </Billboard>} </group> ) }
Comments (0)
Loading comments...