three.js 在 React 组件中的引入方式

537 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

最近3D可视化在商用中的使用越来越广泛,three.js作为前端的3D组件库,能够支持非常多类型的3D模型在浏览器中的渲染和交互操作。目前,团队绝大多数应用多采用React技术栈,除了使用类似@react-three/fiber这样的二次封装库,有没有什么更简单直接的在React组件中使用three.js的方式呢?

安装

yarn add three

引入

// 引入three.js
import * as THREE from 'three';

定义一个用来渲染3D图形的DOM

<div
    id='map'
    ref={mapRef}
    style={{ width: '100%', height: '100%' }}>
</div>

通过useRef绑定

const mapRef = useRef<HTMLDivElement>(null);

在副作用函数中,在存在该节点时,渲染Canvas

useEffect(() => {
    if(mapRef?.current){
        ...
        mapRef?.current?.appendChild(renderer.domElement); //body元素中插入canvas对象
        //执行渲染操作   指定场景、相机作为参数
        renderer.render(scene, camera);
        }
  }, [mapRef]);

组件完整代码如下(DEMO代码为ThreeJS教程中的模版代码):

import React, { useRef, useEffect } from 'react';
import * as THREE from 'three';


function Three() {

    const mapRef = useRef<HTMLDivElement>(null);


    useEffect(() => {
        if (mapRef?.current){
        /**
* 创建场景对象Scene
*/
        var scene = new THREE.Scene();
        /**
         * 创建网格模型
         */
        // var geometry = new THREE.SphereGeometry(60, 40, 40); //创建一个球体几何对象
        var geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个立方体几何对象Geometry
        var material = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材质对象Material
        var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
        scene.add(mesh); //网格模型添加到场景中
        /**
         * 光源设置
         */
        //点光源
        var point = new THREE.PointLight(0xffffff);
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中
        //环境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);
        /**
         * 相机设置
         */
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
        //创建相机对象
        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
        camera.position.set(200, 300, 200); //设置相机位置
        camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
        /**
         * 创建渲染器对象
         */
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height);//设置渲染区域尺寸
        renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
        mapRef?.current?.appendChild(renderer.domElement); //body元素中插入canvas对象
        //执行渲染操作   指定场景、相机作为参数
        renderer.render(scene, camera);
        }
    }, [mapRef]);


    return (
        <>
            <div id='map' ref={mapRef} style={{ width: '100%', height: '100%' }}>
            </div>
        </>

    );
}

export default Three;

这样就可以在React的组件中渲染出Three.js的模型啦

image.png 后续可以根据项目的实际需要,去定义相机、视角等等不同情况下的渲染情况。这种引入方式相对比较直接,但是能够更好的自行理解并解决ThreeJS代码中的问题,是一种比较合适的接入形式。