react+three.js导入外部gltf格式

我把gltf文件放在了public/static下面了。其他地方还没适用。因为之前想导入obj一直没成功,就跟着官网和各种例子成功导入了gltf格式的
gltf存放的位置
然后其他的没啥。看代码吧。大部分我都写了备注
components组件

import React, { useEffect, useRef } from "react";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

function ThreeContainer({ style }) {
  const defaultStyle = {
    height: "50vh",
    width: "50vw",
    backgroundColor: "transparent",
    margin: "0 auto",
  };
  const isContainerRunning = useRef(false);
  const containerRef = useRef(null);
  useEffect(() => {
    console.log(isContainerRunning, "====>", containerRef);
    if (!isContainerRunning.current && containerRef.current) {
      isContainerRunning.current = true;
      const containerWidth = containerRef.current.offsetWidth;
      const containerHeight = containerRef.current.offsetHeight;
      const loader = new GLTFLoader();

      //创建场景
      const scene = new THREE.Scene();

      //创建相机
      const camera = new THREE.PerspectiveCamera(
        75, // 视野角度,视野角值越大,场景中的物体越小
        containerWidth / containerHeight, //宽高比
        0.1, // 近裁剪面
        1000 // 远裁剪面
      );
      camera.position.set(-280, 290, -10);

      // 生成渲染器
      const renderer = new THREE.WebGLRenderer({
        antialias: true, // 抗锯齿
        alpha: true, //用于设置透明度
      });
      renderer.setSize(containerWidth * 0.9995, containerHeight * 0.9995);
      containerRef.current.appendChild(renderer.domElement);
      renderer.outputColorSpace = THREE.SRGBColorSpace; //设置为SRGB颜色空间
      // 设置背景颜色,透明("rgb()", 0)
      renderer.setClearColor(0x000000, 0);

      //添加光源
      const ambientLight = new THREE.AmbientLight("#FF9D6E", 20); // 环境光
      scene.add(ambientLight);
      const directionalLight = new THREE.DirectionalLight("#fff", 5); // 方向光颜色和强度
      directionalLight.position.set(1, 1, 1); // 光源位置
      scene.add(directionalLight);

      //创建控制器
      const controls = new OrbitControls(camera, renderer.domElement);
      controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
      controls.dampingFactor = 0.05; // 阻尼系数
      controls.rotateSpeed = 0.1; // 旋转速度

      // 加载模型
      loadModel(loader, scene);
      // 渲染场景
      // animate(isContainerRunning, camera, renderer, scene);

      function animate(runningFlag, camera, renderer, scene) {
        // console.log(runningFlag, "ruim==>");
        if (!runningFlag.current) {
          controls.autoRotate = true; //是否自动旋转
          //旋转
          // const radius = 140;
          // const angle = Date.now() * 0.0005;
          // const x = Math.cos(angle) * radius;
          // const z = Math.sin(angle) * radius;
          // camera.position.set(x, 200, z);
          // camera.lookAt(0, 50, 0);
          // console.log('controls.target====', controls.target);
        }
        controls.target.set(0, 50, 0); //与lookAt参数保持一致
        requestAnimationFrame(() =>
          animate(runningFlag, camera, renderer, scene)
        );
        controls.update(); //更新控制器状态update()函数内会执行camera.lookAt(controls.target)
        renderer.render(scene, camera);
      }
      function loadModel(loader, scene) {
        loader.load(
          "static/test-glt.gltf",
          function (gltf) {
            isContainerRunning.current = false;
            gltf.scene.traverse(function (child) {
              console.log(child, "child=====>", camera);
              if (child.isMesh) {
                child.frustumCulled = false;
                //模型阴影
                child.castShadow = false;
                //模型自发光(模型自己的颜色)
                // child.material.emissive = child.material.color;
                // child.material.emissiveMap = child.material.map;
              }
            });

            scene.add(gltf.scene);
            animate(isContainerRunning, camera, renderer, scene);
            // 添加点击事件监听器
            // containerRef.current.addEventListener("mousedown", onMouseDown, false)
            // 滚轮事件
            containerRef.current.addEventListener(
              "mousewheel",
              mousewheel,
              false
            );
            function mousewheel(e) {
              // var animationId = ''
              // cancelAnimationFrame(animationId);
              e.preventDefault();
              if (e.deltaY < 0) {
                // 当滚轮向上滚动时
                camera.position.z -= 1; // 向前移动相机
              } else {
                // 当滚轮向下滚动时
                camera.position.z += 1; // 向后移动相机
              }
              console.log(e.deltaY, "====>", camera, scene);
              renderer.render(scene, camera);
            }
            // 窗口大小改变事件
            window.addEventListener("resize", (e) => {
              const width = window.innerWidth;
              const height = window.innerHeight;
              camera.aspect = width / height;
              camera.updateProjectionMatrix();
              renderer.setSize(width, height);
            });
          },
          // called while loading is progressing
          function (xhr) {
            console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
          },
          // called when loading has errors
          function (error) {
            console.log("An error happened");
          }
        );
      }
    }
  }, []);

  return (
    <div>
      <div
        ref={containerRef}
        id="container"
        style={{ ...defaultStyle, ...style }}
      />
      {/* <div onClick={() => { isContainerRunning.current = true }}>
                开始旋转
            </div>
            <div onClick={() => { isContainerRunning.current = false }}>
                停止旋转
            </div> */}
    </div>
  );
}

export default ThreeContainer;

view/indexGltf/index.js

// import "./App.css";
import ThreeContainer from "../../components/ThreeContainer.jsx";

function IndexGltf() {
    return (
        <div>
            <ThreeContainer />
        </div>
    );
}

export default IndexGltf;


App.js文件

import './App.css';
import IndexGltf from './view/indexGltf/index.js';
function App() {
  return (
    <div className="App">
      <IndexGltf />
    </div>
  );
}

export default App;

然后就是文件夹的一个截图吧
所有文件截图

  • 25
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值