threejs react realistic 3d disco ball that is dragable in typescript

You can create a realistic 3D disco ball in React using Three.js and TypeScript. Here's an example:

  1. Install the necessary packages:
npm install three @types/three react-three-fiber @types/react-three-fiber three-stdlib @types/three-stdlib
107 chars
2 lines
  1. Create a new component that will render the 3D scene:
import React, { useRef } from 'react'
import ReactDOM from 'react-dom'
import { Canvas, useFrame, extend, useThree } from 'react-three-fiber'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import * as THREE from 'three'

extend({ OrbitControls })

const Sphere = ({ position }: { position: [number, number, number] }) => {
  const meshRef = useRef<THREE.Mesh>(null)

  useFrame(() => {
    if (meshRef.current) {
      meshRef.current.rotation.x += 0.01
      meshRef.current.rotation.y += 0.01
    }
  })

  return (
    <mesh position={position} ref={meshRef}>
      <sphereGeometry args={[1, 64, 64]} />
      <meshPhysicalMaterial color="#fff" roughness={0.5} metalness={1} />
    </mesh>
  )
}

const DiscoBall = () => {
  const { camera } = useThree()

  return (
    <>
      <Sphere position={[0, 0, -10]} />
      <orbitControls args={[camera]} />
    </>
  )
}

ReactDOM.render(
  <Canvas>
    <ambientLight intensity={0.4} />
    <pointLight position={[10, 10, 10]} />
    <DiscoBall />
  </Canvas>,
  document.getElementById('root'),
)
1075 chars
46 lines
  1. Add drag and drop functionality using the useDrag() hook from react-three-fiber:
import React, { useRef } from 'react'
import ReactDOM from 'react-dom'
import { Canvas, useFrame, extend, useThree } from 'react-three-fiber'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { useDrag } from 'react-use-gesture'
import * as THREE from 'three'

extend({ OrbitControls })

const Sphere = ({ position }: { position: [number, number, number] }) => {
  const meshRef = useRef<THREE.Mesh>(null)

  useFrame(() => {
    if (meshRef.current) {
      meshRef.current.rotation.x += 0.01
      meshRef.current.rotation.y += 0.01
    }
  })

  const bind = useDrag(({ offset: [x, y] }) => {
    const [,, z] = position
    position[0] = x / 50
    position[1] = -y / 50
    position[2] = z
  })

  return (
    <mesh position={position} ref={meshRef} {...bind()}>
      <sphereGeometry args={[1, 64, 64]} />
      <meshPhysicalMaterial color="#fff" roughness={0.5} metalness={1} />
    </mesh>
  )
}

const DiscoBall = () => {
  const { camera } = useThree()

  return (
    <>
      <Sphere position={[0, 0, -10]} />
      <orbitControls args={[camera]} />
    </>
  )
}

ReactDOM.render(
  <Canvas>
    <ambientLight intensity={0.4} />
    <pointLight position={[10, 10, 10]} />
    <DiscoBall />
  </Canvas>,
  document.getElementById('root'),
)
1285 chars
54 lines

This will allow you to drag the disco ball around the screen using your mouse or touch events.

gistlibby LogSnag