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

How to import a Three.js loader into an Angular 6 project

我想使用 Three.js (@types/three/index) 扩展导入到 ng6 项目中的类型定义,并使用一组函数直接附加到同一个 "namespace"。类似于:THREE.myFunction()我不想将 THREE 声明为 any 以抑制类型检查和 linter,我想可以包装一个扩展 THREE 的 vanilla JS 函数使用 TS class/function 然后利用 typings.d.ts.

正在导入加载器

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

的普通函数

我正在尝试将 BinaryLoader 导入到 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"
        ]

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

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

export class ThreeManagerService {
   const loader = new THREE.BinaryLoader();
   ...

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

我得到的警告是:

WARNING in ./src/app/shared/three-manager.service.ts 24:25-43 "export 'BinaryLoader' (imported as 'THREE') was not found in 'three'

静音类型警告和 TS 转译器

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

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

export class ThreeManagerService {
   const loader = new THREE.BinaryLoader();

事实上,我认为这个解决方法非常丑陋 "fix"。我想尽可能多地使用类型系统。

编辑:获取示例以很好地使用 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');

来自:https://github.com/mrdoob/three.js/issues/9562#issuecomment-386522819

相关且有用的 SO 答案:

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

使用 Webpack 的 imports-loader

[...] import-loader is a Webpack plugin allows you to inject a global variable into your module's scope. So the global (!) namespace of your execution context still remains completely clean, but during "compilation", Webpack will be able to figure out where to lookup the binding for a module that only comes with a global variable.

通过this three.js ticket

import "imports?THREE=three!loaders/BinaryLoader";

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

使用三全来提供三个命名空间

项目 three-full 扩展了标准 three.js 库定义的命名空间,添加了几个 "examples" 加载器和控件。使用它而不是经典的 three npm 包,将有可能为最常见和最有用的 类 提供对 ES6 命名空间的全面支持,这些命名空间通常是绝大多数基于 three.js.

npm install --save three-full

然后就可以导入整个命名空间了:

import * as THREE from 'three-full';
...
const loader = new THREE.ColladaLoader();  

如何使用一个小帮助程序库,我想做同样的事情 - 我找到了这个:https://www.npmjs.com/package/ng-three

两步,先安装包再安装类型。

  1. npm 安装三 --save
  2. npm install @types/three --save-dev

然后在您的组件中导入如下: 从 'three';

导入 * 作为三个

类型和包都设置好了。