【问题标题】:Threejs: How could we import a loader into a React application?Threejs:我们如何将加载器导入到 React 应用程序中?
【发布时间】:2018-08-03 10:19:33
【问题描述】:

您好,感谢您阅读此问题。 ????

我正在尝试实现一个用例,我需要将 NRRD 文件加载到 React 应用程序的画布中。

我已经学习了几个月的 Javascript,并在几周内进行了密集的反应,并且我正在被引入 Threejs。

我一直在研究如何整合 React 和 Three,以这个例子作为参考:

How to connect Threejs to React?

在能够将该示例加载为新的反应应用程序之后,我想使用 Threejs 的加载器之一来加载 NRRD 图像。

我尝试了以下方法:

我们的 index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import * as THREE from "three";

class Scene extends React.Component {
    constructor(props) {
        super(props)

        this.start = this.start.bind(this)
        this.stop = this.stop.bind(this)
        this.animate = this.animate.bind(this)
    }

    componentDidMount() {
        const width = this.mount.clientWidth
        const height = this.mount.clientHeight

        const scene = new THREE.Scene()
        const camera = new THREE.PerspectiveCamera(
            75,
            width / height,
            0.1,
            1000
        )

        var loader = new THREE.NRRDLoader();
        loader.load("models/columnasegmentado01.nrrd", function (volume) {
            var sliceZ;


            //z plane

            var indexZ = 0;
            sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));
            scene.add(sliceZ.mesh);

        });

        const renderer = new THREE.WebGLRenderer({antialias: true})


        camera.position.z = 4
        renderer.setClearColor('#000000')
        renderer.setSize(width, height)

        this.scene = scene
        this.camera = camera
        this.renderer = renderer

        this.mount.appendChild(this.renderer.domElement)
        this.start()
    }

    componentWillUnmount() {
        this.stop()
        this.mount.removeChild(this.renderer.domElement)
    }

    start() {
        if (!this.frameId) {
            this.frameId = requestAnimationFrame(this.animate)
        }
    }

    stop() {
        cancelAnimationFrame(this.frameId)
    }

    animate() {


        this.renderScene()
        this.frameId = window.requestAnimationFrame(this.animate)
    }

    renderScene() {
        this.renderer.render(this.scene, this.camera)
    }

    render() {
        return (
            <div
                style={{width: '400px', height: '400px'}}
                ref={(mount) => {
                    this.mount = mount
                }}
            />
        )
    }
}

ReactDOM.render(<Scene/>, document.getElementById('root'))

在 index.html 中,我们将 id 引用为 root 的 div。

这里的问题是:我们如何解决:

Failed to compile
./src/index.js
  Line 26:  'NRRDLoader' is not defined  no-undef

Search for the keywords to learn more about each error.

我问是因为我认为这应该是一个很容易解决的问题,但是我无法弄清楚。

更多详情,我们的 NRRDLoader 位于 node_modules/three/examples/js/loaders 子目录中。

我的第一次尝试是加载文件,将其复制到 rect-app/src/js 目录中,并在 index.html 中使用脚本标签加载它:

<script src="../src/js/NRRDLoader.js" }></script>

并从 index.js 中将其引用为:

/*global THREE.NRRDLoader*/


        var loader = new THREE.NRRDLoader();

但是,有一个冲突,因为三个命名空间是从三个 npm 模块导入的,所以 IDE 没有应用全局。出于这个原因,我们确实有一个Unresolved type: NRRDLoader

作为图片:

我决定尝试这种方法,因为之前我曾建议如何将外部脚本加载到 react 中,当时来自 CDN,而我使用的是全局脚本:

REACT: How could we use an external library as a script, into a class or functional component? Is it possible?

好吧,在阅读了本主题的更多信息后:How to add external javascript file with reactjs

我决定尝试 require 方法:

那么在 index.js 中我们添加:

require('./js/NRRDLoader');

而网页浏览器中的结果是:

Failed to compile
./src/js/NRRDLoader.js
  Line 1:    'THREE' is not defined  no-undef
  Line 3:    'THREE' is not defined  no-undef
  Line 8:    'THREE' is not defined  no-undef
  Line 10:   'THREE' is not defined  no-undef
  Line 16:   'THREE' is not defined  no-undef
  Line 154:  'THREE' is not defined  no-undef
  Line 181:  'THREE' is not defined  no-undef
  Line 181:  'THREE' is not defined  no-undef
  Line 181:  'THREE' is not defined  no-undef
  Line 312:  'THREE' is not defined  no-undef
  Line 332:  'THREE' is not defined  no-undef
  Line 334:  'THREE' is not defined  no-undef
  Line 336:  'THREE' is not defined  no-undef
  Line 342:  'THREE' is not defined  no-undef
  Line 380:  'THREE' is not defined  no-undef
  Line 382:  'THREE' is not defined  no-undef

好吧,至少它识别出了 NRRDLoader。那么我们也应该在该文件中导入三个:

作为结果的代码:

import * as THREE from "three";

THREE.NRRDLoader = function (manager) {

    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;


};

THREE.NRRDLoader.prototype = {

... more code ...

看起来我们在 NRRDLoader 本身也有类似的导入/导出困难:

    Failed to compile
    ./src/js/NRRDLoader.js
    10:21-37 "export 'NRRDLoader' (imported as 'THREE') was not found in 'three'

我的下一个天真的步骤是尝试更改命名空间并从本地 NRRDloader 文件中的 THREE.NRRDLoader 声明中删除 THREE:

import * as THREE from "three";

NRRDLoader = function (manager) {

    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;


};

NRRDLoader.prototype = {

... more code ...

我们最喜欢的网络浏览器报告:

Failed to compile
./src/js/NRRDLoader.js
  Line 3:   'NRRDLoader' is not defined  no-undef
  Line 10:  'NRRDLoader' is not defined  no-undef
  Line 12:  'NRRDLoader' is not defined  no-undef

Search for the keywords to learn more about each error.

所以我认为关键问题是:我们如何在我们自己的项目中包含或要求没有导出实用程序的外部 js 文件? ????

除了解释我为什么要尝试集成 react 和 3 之外,目的是使用 react 为我们提供的有用的方式来构建 UI 组件,结合 3 给出的工具作为此用例所需的负载.

作为说明,我已经正确测试并验证了 Threejs 纯 HTML/Javscript 应用程序可以正确加载来自本地的 NRRD 图像,这里是 github 存储库:

https://github.com/YoneMoreno/LoadNRRDInThreeJSExample

你能帮我弄清楚如何解决这个问题吗?谢谢

有关我在这篇文章中显示的代码的更多详细信息,我们希望在其中包含/reqjuire/从 ThreeJS 导入 NRRDLoader,请参阅我保存尝试的存储库:https://github.com/YoneMoreno/IntegrateReactThreePlainCanvas

【问题讨论】:

  • 我正面临与 assimpJSONLoader 相同的问题。你找到解决办法了吗?
  • 我也有同样的问题。有人知道吗?

标签: javascript reactjs web import three.js


【解决方案1】:

您应该尝试如下使用全局对象:

新建一个three.js文件

import * as THREE from 'three';


window.THREE = THREE; // THREE.NRRDLoader expects THREE to be a global object
require('three/examples/js/loaders/NRRDLoader');


export default window.THREE;

然后在您的组件中从该文件导入三个:

import React from 'react';
import ReactDOM from 'react-dom';
import THREE from "./three"; // note the import here

class Scene extends React.Component {

}

那么您应该可以像现在一样使用 THREE.NRRDLoader:

var loader = new THREE.NRRDLoader();

【讨论】:

    【解决方案2】:

    您可以在 webpack.config 中添加合适的加载器。

     /*
        glb files for 3D models
        ------
        * Copies fonts found within the `src` tree to the `dist` folder
        * Keeps the original file name to the path
      */
      {
        test: /\.(glb|gltf)$/,
        use:
        [
            {
                loader: 'file-loader',
                options:
                {
                    outputPath: 'assets/models/'
                }
            }
        ]
    },
    

    如果您正在使用 React 钩子,这里是一个使用 React.js 从three.js 加载的 3D 模型的示例。

    https://github.com/sarat9/react-threejs-sample/blob/master/src/animations/SoldierMachineAnimation/index.jsx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 2020-02-29
      • 2018-12-17
      • 2022-12-21
      • 2019-12-06
      • 2022-08-02
      • 1970-01-01
      相关资源
      最近更新 更多