如何将Three.js加载程序导入Angular 6项目

sen*_*nza 5 three.js angular-cli angular angular6

我想使用Three.js(@types/three/index)扩展导入到ng6项目中的类型定义,并使用一组将直接附加到相同“名称空间”的函数。类似于:THREE.myFunction()我不想声明三any来抑制类型检查和linter,并且我想可以包装一个使用JS类/功能扩展三个的香草JS函数,然后再利用typings.d.ts

导入装载程序

首先,我想将THREE.js加载程序导入到我的项目中,这通常定义了一个可扩展的vanilla函数THREE

我正在尝试将BinaryLoaderng服务导入ng服务,但不确定如何以正确的方式进行操作。

到目前为止,我所做的是:

  1. npm install three --save
  2. npm install @types/three --save-dev
  3. import * as THREE from 'three';
  4. 将BinaryLoader添加到新的angular.json scripts数组中

angular.json

        "scripts": [
          "./node_modules/three/examples/js/loaders/BinaryLoader.js"
        ]
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利,但是现在我需要创建一个二进制加载器:

import * as THREE from 'three';
// import { BinaryLoader } from 'three';
// import 'three/examples/js/loaders/BinaryLoader';

export class ThreeManagerService {
   const loader = new THREE.BinaryLoader();
   ...
Run Code Online (Sandbox Code Playgroud)

而且我必须找到BinaryLoader@types/three/index某种方式添加的方法。这样,我应该能够扩展类型定义,以便能够创建新类型THREE.BinaryLoader。可以做这样的事情吗?

我得到的警告是:

警告:./src/app/shared/three-manager.service.ts 24:25-43“在'三个'中找不到导出'BinaryLoader'(导入为'三个')

静音类型警告和TS编译器

摆脱警告和错误的解决方法可能是这样的:

import * as THREEJS from 'three';
declare const THREE: any;

export class ThreeManagerService {
   const loader = new THREE.BinaryLoader();
Run Code Online (Sandbox Code Playgroud)

事实是,我认为此解决方法非常难看。我想尽可能多地使用类型系统。

编辑:获取示例以与Intellisense和Typescript一起很好地玩

在等待示例的完整重写以与ES6模块和名称空间兼容的同时,可以定义一个局部模块,该局部模块在以下位置公开并扩展全局变量/src/node_modules/three-extras/index.ts

import * as THREE from 'three';

declare global {
   interface Window {
      THREE: typeof THREE;
   }
}

window.THREE = THREE;

require('three/examples/js/controls/OrbitControls');
require('three/examples/js/loaders/GLTFLoader');
Run Code Online (Sandbox Code Playgroud)

通过:https : //github.com/mrdoob/three.js/issues/9562#issuecomment-386522819

相关且有用的答案:

sen*_*nza 6

我终于找到了两个可行的解决方案(准确地说是=>解决方法)。

使用Webpack的imports-loader

[...] import-loader是一个Webpack插件,可让您将全局变量注入模块的作用域。因此,!执行上下文的global()名称空间仍然保持完全干净,但是在“编译”期间,Webpack将能够找出在哪里查找仅包含全局变量的模块的绑定。

通过此three.js票证

import "imports?THREE=three!loaders/BinaryLoader";
Run Code Online (Sandbox Code Playgroud)

使用此导入,我们告诉Webpack THREE用作npm模块定义的全局变量,'three'并且BinaryLoader不会绑定到任何变量。

使用三全名提供三个名称空间

三全项目扩展了标准three.js库定义的名称空间,并添加了一些“示例”,例如加载器和控件。使用它而不是经典的threenpm包,将可能为最常见和有用的类提供对ES6名称空间的完全支持,这些类通常是基于three.js的大多数项目的一部分。

npm install --save three-full
Run Code Online (Sandbox Code Playgroud)

然后,您可以导入整个名称空间:

import * as THREE from 'three-full';
...
const loader = new THREE.ColladaLoader();  
Run Code Online (Sandbox Code Playgroud)

  • 你不知道我为此苦苦挣扎了多久。我到处寻找答案!太感谢了! (3认同)
  • 我怀疑@K-Dawg,就像我自己以及无数其他人一样,期望能够像大多数其他 NPM 包一样使用 Three.js。我很惊讶自己忘记了网格库是复杂的,幸运的是像yarn/npm这样的工具已经为我们简化了这一点。无论如何,感谢您提供了一系列解决方案的完整答案。许多业力都给你点赞。 (2认同)