react项目中使用three.js(解决纹理贴图路径问题)

一,本文解决如下问题

        1. 在react脚手架的项目中使用three.js

        2. three.js在react中使用动态的纹理贴图遇到的路径问题

        3. this.指向的丢失问题

二,在项目中使用three.js(默认你已经掌握创建react项目)

1.在项目中下载three.js第三方包,如果没有版本要求可直接安装,有版本需求可在后面加@版本

mpm i three

2.安装完成后在组建页面中进行使用,在组件的页面中引入下面的代码,这里我的控制器OrbitControls是修改过源码的,所以引入的是本地文件

   3.做完下列工作后就可以进行three.js的编写了,这里使用的是jsx语法,类组件编程

    3.1在render中添加承载canvas的容器 

  render() {
    return (
        {/* 承载canvas */}
        <div
          ref={this.canvas}
          style={
   
   { width: "780px", height: "720px" }}
        ></div>       
    );
  }

3.2在构造器中声明 场景,相机,渲染器,控制器,并在下面使用箭头函数的方式创建渲染函数(防止this丢失)

  // 构造器
  constructor(props) {
    super(props);
    this.scene = null; 
    this.camera = null;
    this.renderer = null;
    this.controls = null;
     this.canvas = React.createRef(); //承载canvas的容器
  }
 // 初始化场景
  initScene() {
    this.scene = new THREE.Scene();

    // 天空盒,可以不写下面的代码
    let px = require("../public/skybox/nanji1/px.jpg");
    let nx = require("../public/skybox/nanji1/nx.jpg");
    let py = require("../public/skybox/nanji1/py.jpg");
    let ny = require("../public/skybox/nanji1/ny.jpg");
    let pz = require("../public/skybox/nanji1/pz.jpg");
    let nz = require("../public/skybox/nanji1/nz.jpg");
    //初始化天空盒
    this.scene.background = new THREE.CubeTextureLoader().load([
      px,
      nx,
      py,
      ny,
      pz,
      nz,
    ]);
  }

 // 初始化相机
  initCamera() {
    this.camera = new THREE.PerspectiveCamera(
      65,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );
    this.camera.position.set(-5, 0, 15);
  }

  // 初始化渲染器
  initRenderer = () => {
    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(
      this.canvas.current.clientWidth,
      this.canvas.current.clientHeight
    );
    this.renderer.setClearColor(0xeeeeee);
    //告诉渲染器需要阴影效果
    this.renderer.shadowMap.enabled = true;
    // 将场景添加到页面中
    this.canvas.current.appendChild(this.renderer.domElement);
  };
 

  //初始化控制器
  initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    //关闭左键拖拽(修改OrbitControls源码版本)
    this.controls.enablePan = false;
    //关闭可以缩放
    this.controls.enableZoom = false;
  }

    
 //初始化动画函数
  animate = () => {
    requestAnimationFrame(this.animate);
    this.renderer.render(this.scene, this.camera);
  };

   
 // 初始化three.js
  init() {
    this.initScene();
    this.initCamera();
    this.initRenderer();
    this.initControls();
    this.animate();
  }

    

  在react的声明周期中调用

  // 生命周期,页面渲染完毕后调用
  componentDidMount() {
    this.init();
  }

此时运行项目npm run start 可以在页面中得到下面效果,左边就把天空盒渲染出来了,如果你们不加天空盒,应该是一片黑色

 三,解决动态路径问题渲染贴图纹理

       1. 在react访问本地文件,路径要用require进行包装

        2. require 只能是纯静态 或者 静态+动态的格式

       渲染sprite的代码如下

    // 只能是纯静态路径或者 静态+变量
    url = require("../public/" + url);

    // 处理贴图
    const texture = new THREE.TextureLoader().load(url);

    // 合成模型和材质
    const cube = new THREE.BoxGeometry(w, 0, h);
    const MeshBasicMaterial = new THREE.MeshBasicMaterial({ map: texture });
    const mesh = new THREE.Mesh(cube, MeshBasicMaterial);

    // 调整模型的位置
    mesh.position.set(0, -20, 0);
    this.scene.add(mesh);

猜你喜欢

转载自blog.csdn.net/weixin_44275686/article/details/125801410