2023年6月21日发(作者:)
使⽤react-three-fiber加载glb格式3D⽂件,并播放3D模型⾃带动画⼀、react-three-fiber简介使⽤可重⽤、⾃包含的组件以声明⽅式构建您的场景,这些组件对状态做出反应、易于交互并且可以利⽤ React 的⽣态系统。 没有任何限制,⼀切⼯作在这⾥将⽆⼀例外地⼯作。 ⽣态完善。⼆、安装npm install three @react-three/fiber三、基础语法1、创建场景import { Canvas } from '@react-three/fiber'export default function App() { return (
)}Canvas 组件在幕后做了⼀些重要的设置⼯作:它设置了⼀个Scene和⼀个Camera,这是渲染所需的基本构建块它会⾃动处理调整⼤⼩它每⼀帧都渲染我们的场景请注意,Canvas 将调整⼤⼩以适合⽗ div,因此您可以通过更改 css 中
#canvas-container 的
width 和
height 来控制它的⼤⼩。2、添加Mesh组件(属于threejs中物体下的⽹格组件)表⽰基于以三⾓形为(多边形⽹格)的物体的类。 同时也作为其他类的基类 ,⼀个是 中的⼀个基本对象,它⽤于保存在3D 空间中表⽰对象所需的多边形和材质。我们将使⽤BoxGeometry组件为⼏何体和MeshPhongMaterial组件为材料创建⼀个新⽹格。为了将这些对象实际添加到我们的场景中,我们将它们安装在Canvas组件中。import { Canvas } from '@react-three/fiber'export default function App() { return (
)}上述代码会被编译为如下代码:const scene = new ()const camera = new ctiveCamera(75, width / height, 0.1, 1000)const renderer = new enderer()e(width, height)elector('#canvas-container').appendChild(ment)const mesh = new ()ry = new metry()al = new ongMaterial()(mesh)function animate() { requestAnimationFrame(animate) (scene, camera)}animate()当引⼊⼀个mesh组件时,Fiber 会创建⼀个新对象,⼏何和材料也是如此。然后,⼏何体和材料被附加到它们的⽗级。3、构造函数传参集合体构造函数可以传递三个参数:宽度、长度和深度。const geometry = new metry(2, 2, 2)在fiber中可以使⽤如下⽅式代替上述写法:
**请注意,每次更改这些时,都必须重新构造对象! **4、 添加灯光向场景中添加⼀些灯光
参数传递和上述⼏何传递参数类似。
编译成const light = new ionalLight()(0, 0, 5)('red')四、事件1、fiber中事件有13个事件
('click')} onContextMenu={(e) => ('context menu')} onDoubleClick={(e) => ('double click')} onWheel={(e) => ('wheel spins')} onPointerUp={(e) => ('up')} onPointerDown={(e) => ('down')} onPointerOver={(e) => ('over')} onPointerOut={(e) => ('out')} onPointerEnter={(e) => ('enter')} onPointerLeave={(e) => ('leave')} onPointerMove={(e) => ('move')} onPointerMissed={() => ('missed')} onUpdate={(self) => ('props have been updated')}/>2、各个事件作⽤事件名称onClickonContextMenuonDoubleClickonWheelonPointerUponPointerDownonPointerOveronPointerOutonPointerEnteronPointerLeaveonPointerMoveonPointerMissedonUpdate作⽤点击⽹格做出响应在纹理上右击⿏标事件在纹理上双击事件在纹理上滚动⿏标滚轮触发的事件⿏标抬起事件⿏标按下事件⿏标滑过⿏标离开事件回调进⼊事件回调离开⿏标移动事件消失回调视图更新回调3、点击放⼤例⼦ setActive(!active)} ref={myMesh}> 五、模型加载1、引⼊资源注意: 引⼊资源必须放在public⽂件夹下,否则都会引⼊失败import React, { useRef } from 'react'import { useGLTF } from '@react-three/drei'export default function Model(props) { const group = useRef() const gltf = useGLTF('/images/'); // public下的images return ( )}d('/images/'); // 预加载2、使⽤资源import { Canvas } from "@react-three/fiber";import { Suspense } from "react";import { Environment } from "@react-three/drei";import Model from "./Model";import './';import Loader from './Loader';export default function App() { return (
);}3、资源过⼤过渡动画import { Html, useProgress } from '@react-three/drei'function Loader() { const { progress } = useProgress() return {progress} % loaded}六、基本动画1、 useFrameuseFrame是⼀个 Fiber 挂钩,可让您在 Fiber 渲染循环的每⼀帧上执⾏代码。这可以有很多⽤途,但我们将专注于⽤它构建动画。重要的是要记住Fiber 钩⼦只能在⽗级内部调⽤!2、使⽤useRef在每⼀帧直接改变我们的⽹格。⾸先,我们必须reference通过useRefReact 钩⼦获取它:import React, { useRef } from "react";import { useGLTF } from "@react-three/drei";import { useFrame } from '@react-three/fiber';export default function Model(props) { const group = useRef(); const gltf = useGLTF("/images/"); useFrame(({clock}) => { on.y = (psedTime()); }); return ( );}d("/images/");七、react-spring动画,可以实现和css动画⼀样效果1、安装npm install three @react-spring/three2、使⽤import { useSpring, animated } from '@react-spring/three'useSpring - 将值转换为动画值的钩⼦animated-⽤于你的DOM代替或⽹状的部件,所以不是⽤mesh你,如果你希望它受以下因素影响react-springimport React, { useRef, useState } from "react";import { useGLTF } from "@react-three/drei";import { useFrame } from '@react-three/fiber';import { useSpring, animated, config } from '@react-spring/three';export default function Model(props) { const group = useRef(); const gltf = useGLTF("/images/"); useFrame(({clock}) => { on.y = (psedTime()); }); const [active, setActive]=useState(false); const { scale } = useSpring({ scale: active ? 1.5 : 1, config: }); return ( < ref={group} {...props} dispose={null} scale={scale} onClick={() => setActive(!active)}> > );}d("/images/");您会看到它不仅从⼀个值跳到另⼀个值,⽽是在两个值之间平滑地进⾏动画处理。 我想做的最后⼀步是为动画添加⼀些摇摆不定的效果,为此我们可以config从react-spring以下位置导⼊对象:import { useSpring, animated, config } from 'react-spring/three';最后,当我们调⽤钩⼦时,我们可以为 config 传递⼀个值,然后让我们传递wobbly配置:const { scale } = useSpring({ scale: active ? 1.5 : 1, config: ,});⼋、加载windows的glb⽂件,并播放3D的动画import React, { useState, useEffect, useCallback } from "react";import { useGLTF, useAnimations } from "@react-three/drei";import { useFrame } from "@react-three/fiber";import { useSpring, animated, config } from "@react-spring/three";export default function Model(props) { // const group = useRef(); const { scene, animations } = useGLTF("/images/"); const { actions, names, ref } = useAnimations(animations); useFrame(({ clock }) => { on.y = (psedTime()); }); const [active, setActive] = useState(false); const { scale } = useSpring({ scale: active ? 1.5 : 1, config: , }); const [activeIndex, setActiveIndex]=useState(0); useEffect(() => { (actions, "actions", animations, names); if (actions) { (actions, "actions", animations, names); actions[names[activeIndex]].reset().fadeIn(0.5).play(); } // In the clean-up phase, fade it out return () => actions[names[activeIndex]].fadeOut(0.5); }, [actions, names, activeIndex]); const handleChangeAnmition=useCallback(()=>{ if(activeIndex<-1){ setActiveIndex(activeIndex+1); }else{ setActiveIndex(0); } }, [activeIndex]); return ( < ref={ref} {...props} dispose={null} scale={scale} onPointerOver={() => setActive(!active)} onClick={handleChangeAnmition} > > );}d("/images/");九、完整代码rt React, { useState, useEffect, useCallback } from "react";import { useGLTF, useAnimations } from "@react-three/drei";import { useFrame } from "@react-three/fiber";import { useSpring, animated, config } from "@react-spring/three";export default function Model(props) { // const group = useRef(); const { scene, animations } = useGLTF("/images/"); const { actions, names, ref } = useAnimations(animations); useFrame(({ clock }) => { on.y = (psedTime()); }); const [active, setActive] = useState(false); const { scale } = useSpring({ scale: active ? 0.6 : 1, config: , }); const [activeIndex, setActiveIndex]=useState(0); useEffect(() => { (actions, "actions", animations, names); if (actions) { actions[names[activeIndex]].reset().fadeIn(0.5).play(); } return () => actions[names[activeIndex]].fadeOut(0.5); }, [actions, names, activeIndex]); const handleChangeAnmition=useCallback(()=>{ if(activeIndex<-1){ setActiveIndex(activeIndex+1); }else{ setActiveIndex(0); } }, [activeIndex]); return ( < ref={ref} {...props} dispose={null} scale={scale} onPointerOver={() => setActive(!active)} onClick={handleChangeAnmition} > > );}d("/images/");rt { Html, useProgress } from "@react-three/drei";export default function Loader() { const { progress } = useProgress(); return ( {progress ? parseInt(progress) : 0} % loaded );}rt { Canvas } from "@react-three/fiber";import { Suspense } from "react";import { Environment } from "@react-three/drei";import Model from "./Model";import './';import Loader from './Loader';export default function App() { return ( );}⼗、代码地址效果展⽰:2023年6月21日发(作者:)
使⽤react-three-fiber加载glb格式3D⽂件,并播放3D模型⾃带动画⼀、react-three-fiber简介使⽤可重⽤、⾃包含的组件以声明⽅式构建您的场景,这些组件对状态做出反应、易于交互并且可以利⽤ React 的⽣态系统。 没有任何限制,⼀切⼯作在这⾥将⽆⼀例外地⼯作。 ⽣态完善。⼆、安装npm install three @react-three/fiber三、基础语法1、创建场景import { Canvas } from '@react-three/fiber'export default function App() { return (
)}Canvas 组件在幕后做了⼀些重要的设置⼯作:它设置了⼀个Scene和⼀个Camera,这是渲染所需的基本构建块它会⾃动处理调整⼤⼩它每⼀帧都渲染我们的场景请注意,Canvas 将调整⼤⼩以适合⽗ div,因此您可以通过更改 css 中 #canvas-container 的
width 和
height 来控制它的⼤⼩。2、添加Mesh组件(属于threejs中物体下的⽹格组件)表⽰基于以三⾓形为(多边形⽹格)的物体的类。 同时也作为其他类的基类 ,⼀个是 中的⼀个基本对象,它⽤于保存在3D 空间中表⽰对象所需的多边形和材质。我们将使⽤BoxGeometry组件为⼏何体和MeshPhongMaterial组件为材料创建⼀个新⽹格。为了将这些对象实际添加到我们的场景中,我们将它们安装在Canvas组件中。import { Canvas } from '@react-three/fiber'export default function App() { return (
)}上述代码会被编译为如下代码:const scene = new ()const camera = new ctiveCamera(75, width / height, 0.1, 1000)const renderer = new enderer()e(width, height)elector('#canvas-container').appendChild(ment)const mesh = new ()ry = new metry()al = new ongMaterial()(mesh)function animate() { requestAnimationFrame(animate) (scene, camera)}animate()当引⼊⼀个mesh组件时,Fiber 会创建⼀个新对象,⼏何和材料也是如此。然后,⼏何体和材料被附加到它们的⽗级。3、构造函数传参集合体构造函数可以传递三个参数:宽度、长度和深度。const geometry = new metry(2, 2, 2)在fiber中可以使⽤如下⽅式代替上述写法:**请注意,每次更改这些时,都必须重新构造对象! **4、 添加灯光向场景中添加⼀些灯光参数传递和上述⼏何传递参数类似。编译成const light = new ionalLight()(0, 0, 5)('red')四、事件1、fiber中事件有13个事件 ('click')} onContextMenu={(e) => ('context menu')} onDoubleClick={(e) => ('double click')} onWheel={(e) => ('wheel spins')} onPointerUp={(e) => ('up')} onPointerDown={(e) => ('down')} onPointerOver={(e) => ('over')} onPointerOut={(e) => ('out')} onPointerEnter={(e) => ('enter')} onPointerLeave={(e) => ('leave')} onPointerMove={(e) => ('move')} onPointerMissed={() => ('missed')} onUpdate={(self) => ('props have been updated')}/>2、各个事件作⽤事件名称onClickonContextMenuonDoubleClickonWheelonPointerUponPointerDownonPointerOveronPointerOutonPointerEnteronPointerLeaveonPointerMoveonPointerMissedonUpdate作⽤点击⽹格做出响应在纹理上右击⿏标事件在纹理上双击事件在纹理上滚动⿏标滚轮触发的事件⿏标抬起事件⿏标按下事件⿏标滑过⿏标离开事件回调进⼊事件回调离开⿏标移动事件消失回调视图更新回调3、点击放⼤例⼦ setActive(!active)} ref={myMesh}> 五、模型加载1、引⼊资源注意: 引⼊资源必须放在public⽂件夹下,否则都会引⼊失败import React, { useRef } from 'react'import { useGLTF } from '@react-three/drei'export default function Model(props) { const group = useRef() const gltf = useGLTF('/images/'); // public下的images return ( )}d('/images/'); // 预加载2、使⽤资源import { Canvas } from "@react-three/fiber";import { Suspense } from "react";import { Environment } from "@react-three/drei";import Model from "./Model";import './';import Loader from './Loader';export default function App() { return (
);}3、资源过⼤过渡动画import { Html, useProgress } from '@react-three/drei'function Loader() { const { progress } = useProgress() return {progress} % loaded}六、基本动画1、 useFrameuseFrame是⼀个 Fiber 挂钩,可让您在 Fiber 渲染循环的每⼀帧上执⾏代码。这可以有很多⽤途,但我们将专注于⽤它构建动画。重要的是要记住Fiber 钩⼦只能在⽗级内部调⽤!2、使⽤useRef在每⼀帧直接改变我们的⽹格。⾸先,我们必须reference通过useRefReact 钩⼦获取它:import React, { useRef } from "react";import { useGLTF } from "@react-three/drei";import { useFrame } from '@react-three/fiber';export default function Model(props) { const group = useRef(); const gltf = useGLTF("/images/"); useFrame(({clock}) => { on.y = (psedTime()); }); return ( );}d("/images/");七、react-spring动画,可以实现和css动画⼀样效果1、安装npm install three @react-spring/three2、使⽤import { useSpring, animated } from '@react-spring/three'useSpring - 将值转换为动画值的钩⼦animated-⽤于你的DOM代替或⽹状的部件,所以不是⽤mesh你,如果你希望它受以下因素影响react-springimport React, { useRef, useState } from "react";import { useGLTF } from "@react-three/drei";import { useFrame } from '@react-three/fiber';import { useSpring, animated, config } from '@react-spring/three';export default function Model(props) { const group = useRef(); const gltf = useGLTF("/images/"); useFrame(({clock}) => { on.y = (psedTime()); }); const [active, setActive]=useState(false); const { scale } = useSpring({ scale: active ? 1.5 : 1, config: }); return ( < ref={group} {...props} dispose={null} scale={scale} onClick={() => setActive(!active)}> > );}d("/images/");您会看到它不仅从⼀个值跳到另⼀个值,⽽是在两个值之间平滑地进⾏动画处理。 我想做的最后⼀步是为动画添加⼀些摇摆不定的效果,为此我们可以config从react-spring以下位置导⼊对象:import { useSpring, animated, config } from 'react-spring/three';最后,当我们调⽤钩⼦时,我们可以为 config 传递⼀个值,然后让我们传递wobbly配置:const { scale } = useSpring({ scale: active ? 1.5 : 1, config: ,});⼋、加载windows的glb⽂件,并播放3D的动画import React, { useState, useEffect, useCallback } from "react";import { useGLTF, useAnimations } from "@react-three/drei";import { useFrame } from "@react-three/fiber";import { useSpring, animated, config } from "@react-spring/three";export default function Model(props) { // const group = useRef(); const { scene, animations } = useGLTF("/images/"); const { actions, names, ref } = useAnimations(animations); useFrame(({ clock }) => { on.y = (psedTime()); }); const [active, setActive] = useState(false); const { scale } = useSpring({ scale: active ? 1.5 : 1, config: , }); const [activeIndex, setActiveIndex]=useState(0); useEffect(() => { (actions, "actions", animations, names); if (actions) { (actions, "actions", animations, names); actions[names[activeIndex]].reset().fadeIn(0.5).play(); } // In the clean-up phase, fade it out return () => actions[names[activeIndex]].fadeOut(0.5); }, [actions, names, activeIndex]); const handleChangeAnmition=useCallback(()=>{ if(activeIndex<-1){ setActiveIndex(activeIndex+1); }else{ setActiveIndex(0); } }, [activeIndex]); return ( < ref={ref} {...props} dispose={null} scale={scale} onPointerOver={() => setActive(!active)} onClick={handleChangeAnmition} > > );}d("/images/");九、完整代码rt React, { useState, useEffect, useCallback } from "react";import { useGLTF, useAnimations } from "@react-three/drei";import { useFrame } from "@react-three/fiber";import { useSpring, animated, config } from "@react-spring/three";export default function Model(props) { // const group = useRef(); const { scene, animations } = useGLTF("/images/"); const { actions, names, ref } = useAnimations(animations); useFrame(({ clock }) => { on.y = (psedTime()); }); const [active, setActive] = useState(false); const { scale } = useSpring({ scale: active ? 0.6 : 1, config: , }); const [activeIndex, setActiveIndex]=useState(0); useEffect(() => { (actions, "actions", animations, names); if (actions) { actions[names[activeIndex]].reset().fadeIn(0.5).play(); } return () => actions[names[activeIndex]].fadeOut(0.5); }, [actions, names, activeIndex]); const handleChangeAnmition=useCallback(()=>{ if(activeIndex<-1){ setActiveIndex(activeIndex+1); }else{ setActiveIndex(0); } }, [activeIndex]); return ( < ref={ref} {...props} dispose={null} scale={scale} onPointerOver={() => setActive(!active)} onClick={handleChangeAnmition} > > );}d("/images/");rt { Html, useProgress } from "@react-three/drei";export default function Loader() { const { progress } = useProgress(); return ( {progress ? parseInt(progress) : 0} % loaded );}rt { Canvas } from "@react-three/fiber";import { Suspense } from "react";import { Environment } from "@react-three/drei";import Model from "./Model";import './';import Loader from './Loader';export default function App() { return ( );}⼗、代码地址效果展⽰:
发布评论