动态地将threejs加载到create react应用中

时间:2018-07-10 05:38:10

标签: javascript reactjs three.js create-react-app

当我动态加载Three.js时,仍然找不到变量THREE。 我已经使用create-react-app创建了一个React项目,并将三个js文件复制到了公共文件夹中。结构如下:

src
public
├── js
│   └── threejs
│       ├── Detector.js
│       ├── OrbitControls.js
│       ├── postprocessing
│       │   ├── BloomPass.js
│       │   ├── ShaderPass.js
│       │   └── ...
│       ├── shaders
│       │   ├── BasicShader.js
│       │   ├── BleachBypassShader.js
│       │   ├── ....
│       ├── three.js
│       └── three.min.js

我创建了下面的类,该类可动态加载three.js和examples / js文件夹中的任何文件,并触发onLoaded回调:

// Dependencies
import React from 'react';

export default class ThreeJsLoader extends React.Component {

    constructor(props) {
        super(props);   
        this.unloaded = [
            '/js/threejs/three.js',
            '/js/threejs/OrbitControls.js'
        ];
        this.loaded = [];
    }

    loadScript(address) {
        let script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');  // optional
        script.setAttribute('src', address);
        script.onload = () => {
            this.loaded.push(address);
            this.checkLoaded();
        };
        document.getElementsByTagName('head')[0].appendChild(script);
    }

    checkLoaded() {
        if(this.loaded.length >= this.unloaded.length) {
            if(this.props.onLoaded) {
                this.props.onLoaded();
            }
        }
    }

    componentDidMount() {
        while(true) {
            let script = this.unloaded.shift();
            let script_path = `${process.env.PUBLIC_URL}${script}`;
            if(script) {
                this.loadScript(script_path);
            }
            else {
                break;
            }
        }
    }

    render() {
        return null;
    }
}

这是脚本的使用方式:

import React from 'react';
import ThreeJsLoader from './threejs_loader';

export default class PageBackground extends React.Component {

    constructor(props) {
        super(props);
        this.background_ref = React.createRef();
    }

    loadScene() {
        let scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xcccccc );

        let renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        this.background_ref.current.appendChild( renderer.domElement );

        let camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
        camera.position.set( 400, 200, 0 );

        // controls
        let controls = new THREE.OrbitControls( camera, renderer.domElement );
    }

    render() {
        return (
            <div>
                <ThreeJsLoader onLoaded={ () => this.loadScene() } />
                <div ref={this.background_ref} > </div>
            </div>
        );
    }
}

我已经测试了代码,并且可以正确加载脚本。但是,出现以下错误:

./src/page_background.jsx
  Line 36:  'THREE' is not defined  no-undef
  Line 37:  'THREE' is not defined  no-undef

1 个答案:

答案 0 :(得分:0)

不幸的是,我不得不弹出并禁用EsLint,并且还禁用了不允许从外部源加载源的功能。我在某处读到这很危险,但我认为可以修改适当的文件系统权限限制。