使用 React-Three-Fiber
Using React-Three-Fiber
我目前正在使用 React Three Fiber 来简单地渲染太阳和围绕它运行的地球以对其进行测试。但是,每次我 运行 开发服务器进行测试时,我都添加了将纹理应用于各个球体的代码,球体无法渲染。我试过寻找有同样问题的人,但没有任何运气。这是我的程序代码。
import React, { useRef, useState } from 'react'
import { Canvas, useFrame, useLoader } from 'react-three-fiber'
import { TextureLoader } from 'three/src/loaders/TextureLoader'
import { useTexture } from "@react-three/drei";
function Sun(props) {
const [colorMap] = useTexture(['Sun_texture.jpg'])
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 5
})
return (
<mesh
{...props}
ref={mesh}
scale={[1, 1, 1]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereGeometry args={[0.5, 100, 100]} map={colorMap} />
<meshStandardMaterial map={colorMap} transparent={true} emissive={'#444444'} emissiveIntensity={0.3}/>
</mesh>
)
}
function Earth(props) {
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
const [colorMap] = useTexture(['Earth_texture.jpg'])
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.position.x = 4 * Math.sin(time / 10)
mesh.current.position.y = 0
mesh.current.position.z = 4 * Math.cos(time / 10)
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 2
})
return (
<mesh
{...props}
ref={mesh}
scale={[0.5, 0.5, 0.5]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereBufferGeometry args={[0.5, 40, 40]} map={colorMap} />
<meshStandardMaterial map={colorMap} />
</mesh>
)
}
export default function App() {
return (
<Canvas camera={{position: [0, 2, 8]}}>
<Sun position={[0, 0, 0]} />
<Earth position={[3, 0, 0]} />
<ambientLight intensity={0.01}/>
<pointLight position={[0, 0, 0]}/>
<spotLight position={[1.5, 0, 0]} distance={4}/>
<spotLight position={[-1.5, 0, 0]} distance={4}/>
<spotLight position={[0, 0, -1.5]} distance={4}/>
<spotLight position={[0, 0, 1.5]} distance={4}/>
<spotLight position={[0, 1.5, 0]} distance={4}/>
<spotLight position={[0, -1.5, 0]} distance={4}/>
</Canvas>
)
}
特别是纹理部分是个问题,但我找不到任何问题。
const [colorMap] = useTexture(['Sun_texture.jpg'])
...
<sphereGeometry args={[0.5, 100, 100]} map={colorMap} />
<meshStandardMaterial map={colorMap} transparent={true} emissive={'#444444'} emissiveIntensity={0.3}/>
您需要将 <Earth>
组件放在 <Suspense>
中,因为它需要加载纹理,所以方法是使用悬念等待它加载。
您可以通过执行以下操作指定要在加载时显示的对象
<suspense fallback={<loadingComponent />} >
所以这会给你类似的东西:
import React, { useRef, useState, Suspense } from 'react'
import { Canvas, useFrame, useLoader } from 'react-three-fiber'
import { TextureLoader } from 'three/src/loaders/TextureLoader'
import { useTexture } from "@react-three/drei";
function Sun(props) {
const [colorMap] = useTexture(['Sun_texture.jpg'])
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 5
})
return (
<mesh
{...props}
ref={mesh}
scale={[1, 1, 1]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereGeometry args={[0.5, 100, 100]} map={colorMap} />
<meshStandardMaterial map={colorMap} transparent={true} emissive={'#444444'} emissiveIntensity={0.3}/>
</mesh>
)
}
function Earth(props) {
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
const [colorMap] = useTexture(['Earth_texture.jpg'])
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.position.x = 4 * Math.sin(time / 10)
mesh.current.position.y = 0
mesh.current.position.z = 4 * Math.cos(time / 10)
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 2
})
return (
<mesh
{...props}
ref={mesh}
scale={[0.5, 0.5, 0.5]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereBufferGeometry args={[0.5, 40, 40]} map={colorMap} />
<meshStandardMaterial map={colorMap} />
</mesh>
)
}
export default function App() {
return (
<Canvas camera={{position: [0, 2, 8]}}>
<Sun position={[0, 0, 0]} />
<Suspense fallback={<Loading />}>
<Earth position={[3, 0, 0]} />
</Suspense>
<ambientLight intensity={0.01}/>
<pointLight position={[0, 0, 0]}/>
<spotLight position={[1.5, 0, 0]} distance={4}/>
<spotLight position={[-1.5, 0, 0]} distance={4}/>
<spotLight position={[0, 0, -1.5]} distance={4}/>
<spotLight position={[0, 0, 1.5]} distance={4}/>
<spotLight position={[0, 1.5, 0]} distance={4}/>
<spotLight position={[0, -1.5, 0]} distance={4}/>
</Canvas>
)
}
您可以在 codeSandbox 上找到有关 react-three-fiber 的精彩内容和示例。
如果您需要更高的精度,请告诉我。
我目前正在使用 React Three Fiber 来简单地渲染太阳和围绕它运行的地球以对其进行测试。但是,每次我 运行 开发服务器进行测试时,我都添加了将纹理应用于各个球体的代码,球体无法渲染。我试过寻找有同样问题的人,但没有任何运气。这是我的程序代码。
import React, { useRef, useState } from 'react'
import { Canvas, useFrame, useLoader } from 'react-three-fiber'
import { TextureLoader } from 'three/src/loaders/TextureLoader'
import { useTexture } from "@react-three/drei";
function Sun(props) {
const [colorMap] = useTexture(['Sun_texture.jpg'])
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 5
})
return (
<mesh
{...props}
ref={mesh}
scale={[1, 1, 1]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereGeometry args={[0.5, 100, 100]} map={colorMap} />
<meshStandardMaterial map={colorMap} transparent={true} emissive={'#444444'} emissiveIntensity={0.3}/>
</mesh>
)
}
function Earth(props) {
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
const [colorMap] = useTexture(['Earth_texture.jpg'])
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.position.x = 4 * Math.sin(time / 10)
mesh.current.position.y = 0
mesh.current.position.z = 4 * Math.cos(time / 10)
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 2
})
return (
<mesh
{...props}
ref={mesh}
scale={[0.5, 0.5, 0.5]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereBufferGeometry args={[0.5, 40, 40]} map={colorMap} />
<meshStandardMaterial map={colorMap} />
</mesh>
)
}
export default function App() {
return (
<Canvas camera={{position: [0, 2, 8]}}>
<Sun position={[0, 0, 0]} />
<Earth position={[3, 0, 0]} />
<ambientLight intensity={0.01}/>
<pointLight position={[0, 0, 0]}/>
<spotLight position={[1.5, 0, 0]} distance={4}/>
<spotLight position={[-1.5, 0, 0]} distance={4}/>
<spotLight position={[0, 0, -1.5]} distance={4}/>
<spotLight position={[0, 0, 1.5]} distance={4}/>
<spotLight position={[0, 1.5, 0]} distance={4}/>
<spotLight position={[0, -1.5, 0]} distance={4}/>
</Canvas>
)
}
特别是纹理部分是个问题,但我找不到任何问题。
const [colorMap] = useTexture(['Sun_texture.jpg'])
...
<sphereGeometry args={[0.5, 100, 100]} map={colorMap} />
<meshStandardMaterial map={colorMap} transparent={true} emissive={'#444444'} emissiveIntensity={0.3}/>
您需要将 <Earth>
组件放在 <Suspense>
中,因为它需要加载纹理,所以方法是使用悬念等待它加载。
您可以通过执行以下操作指定要在加载时显示的对象
<suspense fallback={<loadingComponent />} >
所以这会给你类似的东西:
import React, { useRef, useState, Suspense } from 'react'
import { Canvas, useFrame, useLoader } from 'react-three-fiber'
import { TextureLoader } from 'three/src/loaders/TextureLoader'
import { useTexture } from "@react-three/drei";
function Sun(props) {
const [colorMap] = useTexture(['Sun_texture.jpg'])
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 5
})
return (
<mesh
{...props}
ref={mesh}
scale={[1, 1, 1]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereGeometry args={[0.5, 100, 100]} map={colorMap} />
<meshStandardMaterial map={colorMap} transparent={true} emissive={'#444444'} emissiveIntensity={0.3}/>
</mesh>
)
}
function Earth(props) {
const mesh = useRef()
const [state, setState] = useState({ isHovered: false, isActive: false })
const [colorMap] = useTexture(['Earth_texture.jpg'])
useFrame((state) => {
const time = state.clock.getElapsedTime()
mesh.current.position.x = 4 * Math.sin(time / 10)
mesh.current.position.y = 0
mesh.current.position.z = 4 * Math.cos(time / 10)
mesh.current.rotation.z = 0
mesh.current.rotation.x = 0
mesh.current.rotation.y = time / 2
})
return (
<mesh
{...props}
ref={mesh}
scale={[0.5, 0.5, 0.5]}
onPointerOver={(e) => setState({ ...state, isHovered: true })}
onPointerOut={(e) => setState({ ...state, isHovered: false })}>
<sphereBufferGeometry args={[0.5, 40, 40]} map={colorMap} />
<meshStandardMaterial map={colorMap} />
</mesh>
)
}
export default function App() {
return (
<Canvas camera={{position: [0, 2, 8]}}>
<Sun position={[0, 0, 0]} />
<Suspense fallback={<Loading />}>
<Earth position={[3, 0, 0]} />
</Suspense>
<ambientLight intensity={0.01}/>
<pointLight position={[0, 0, 0]}/>
<spotLight position={[1.5, 0, 0]} distance={4}/>
<spotLight position={[-1.5, 0, 0]} distance={4}/>
<spotLight position={[0, 0, -1.5]} distance={4}/>
<spotLight position={[0, 0, 1.5]} distance={4}/>
<spotLight position={[0, 1.5, 0]} distance={4}/>
<spotLight position={[0, -1.5, 0]} distance={4}/>
</Canvas>
)
}
如果您需要更高的精度,请告诉我。