如何在React组件中使用THREE.js、THREEx及AR.js CDN,不使用Fiber与Aframe
问题原因
你遇到的THREE is not defined报错是ESLint的静态检查错误,不是运行时真实缺失对象:你在index.html中引入的脚本加载完成后会把THREE、THREEx挂载到window全局对象上,这也是你在F12控制台能正常访问这两个对象的原因,不需要额外等待脚本加载。ESLint默认不知道全局有这两个变量,因此抛出规则错误阻断了项目运行。
解决步骤
- 第一步:处理ESLint报错,二选一即可:
- 调用时直接从
window对象读取:把代码中所有THREE替换为window.THREE,THREEx替换为window.THREEx,无需额外配置即可解决报错 - 声明全局变量:在
ARcomponent.js文件最顶部添加注释/* global THREE THREEx */,告知ESLint这两个变量是全局存在的,不需要检查定义
- 调用时直接从
- 第二步:修正静态资源路径(如果使用create-react-app等脚手架)
所有静态依赖的js文件要放到项目的public目录下,index.html中引入脚本的路径统一添加%PUBLIC_URL%前缀,避免打包后路径失效,示例:<script src='%PUBLIC_URL%/libs/three/example/vendor/three.js/build/three.js'></script> - 第三步:补全组件逻辑
你当前初始化的WebGLRenderer没有挂载到组件的DOM节点上,需要给渲染容器加ref,在componentDidMount中挂载canvas,同时在组件卸载时销毁实例避免内存泄漏,参考代码:/* global THREE THREEx */ import React, { Component } from 'react' export class ARcomponent extends Component { canvasRef = React.createRef() renderer = null scene = null camera = null componentDidMount() { // init renderer this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); // 挂载canvas到组件容器 this.canvasRef.current.appendChild(this.renderer.domElement) // 后续AR.js初始化逻辑正常写即可 // ... } componentWillUnmount() { // 销毁实例释放内存 this.renderer.dispose() this.scene = null this.camera = null } render() { return ( <div className="canvas" ref={this.canvasRef}></div> ) } } export default ARcomponent - 可选优化:如果不想通过script引入Three.js,可以npm安装后挂载到全局
执行npm install three安装对应版本的Three.js,然后在项目入口文件index.js中添加:
之后就可以删掉import * as THREE from 'three' window.THREE = THREEindex.html中引入Three.js的script标签,版本管理更方便。
内容的提问来源于stack exchange,提问作者Suisse
相关产品推荐
相关产品推荐

