在 TypeScript 中使用三个 Js + OrbitControls

Posted

技术标签:

【中文标题】在 TypeScript 中使用三个 Js + OrbitControls【英文标题】:Using Threejs + OrbitContols in TypeScript 【发布时间】:2013-10-26 23:57:07 【问题描述】:

我无法获得 this 在 TypeScript 中使用上述组合的示例。

我的 html <head> 中有 <script src="lib/three.min.js"></script><script src="lib/OrbitControls.js"></script><body> 中有打字稿文件:

/// <reference path="lib\three.d.ts" />
...
this.controls = new THREE.OrbitControls(this.camera); //there's the error
this.controls.addEventListener('change', this.render);
...

this.controls.update();

在定期调用render() 函数。据我所知,设置与示例相同,但在编译 OrbitControls 构造函数行时给了我一个巨大的错误(缩写):

The property 'OrbitControls' does not exist on value of type 'REVISION:string;   
CullFace: [x: number ...

我猜这个错误中有整个 Threejs,因为 Visual Studio 在我点击它的那一刻就崩溃了 :)。感谢您的帮助。

【问题讨论】:

【参考方案1】:

感觉有点傻,因为解决方案(或至少解决方法)结果非常简单......

只需声明OrbitControls 变量:

declare var THREE.OrbitControls: any; // even "declare var THREE.OrbitControls;" will do the trick

仍有一些编译错误,但它可以工作。

【讨论】:

我认为这不是一个好主意。您应该尽量避免使用 any 来绕过打字稿问题。这是一种会掉下来的创可贴。 @JuanSolano 我同意,我的“解决方案”绝对是暂时的【参考方案2】:

答案在 Eclipse 打字稿中对我不起作用,因为它与之前的参考声明冲突。但以下工作:

declare module THREE export var OrbitControls

【讨论】:

【参考方案3】:

虽然之前的答案可能在某种程度上可行,但您应该使用现成的definition files from DefinitelyTyped。他们还定义了OrbitControl 的属性和方法。

【讨论】:

链接失效 抱歉,这里是更新的链接:github.com/DefinitelyTyped/DefinitelyTyped/blob/master/three/… 这并没有回答如何引入 OrbitControls 本身的问题。【参考方案4】:

在添加了三轨道控制类型和三轨道控制 npm 包之后(为什么它们的名称不一样?),我仍然无法让它在 Typescript 中工作。这最终对我有用,以防它对不想使用该解决方法的其他人有所帮助:

import * as three from 'three';
three.OrbitControls = require('three-orbit-controls')(three);

let camera = new three.PerspectiveCamera(75, aspectRatio, 1, 1000);
let renderer = new three.WebGLRenderer();
let controls = new three.OrbitControls(camera, renderer.domElement);

截至今天,OrbitControls npm 包似乎正在使用旧样式的导出,它需要在 Three 库中传递的旧样式 require 语句。

【讨论】:

【参考方案5】:

我尝试了一些建议的解决方案,但无法使其正常工作,因此经过一些实验后,我最终得到:

import * as THREE from 'three';
import OrbitControlsLibrary = require('three-orbit-controls');
var OrbitControls = OrbitControlsLibrary(THREE);
...
this.controls = new OrbitControls(this.camera);

我正在使用 webpack 捆绑,因此我不必在 HTML 模板中添加脚本标签。

【讨论】:

【参考方案6】:

在这个问题上花了几个小时后,我最终创建了一个新包:three-orbitcontrols-ts

import * as THREE from 'three';
import  OrbitControls  from 'three-orbitcontrols-ts';

const controls = new OrbitControls(camera, renderer.domElement);

【讨论】:

除了轨迹球控件,有没有人发现类似的东西? 干得好,但现在我们有另一个不同步的包。例如,这个包已经缺少我正在使用的其他一些组件使用的saveState 例程。【参考方案7】:

在 ts 之外:

var THREEa = THREE;

ts内部:

var controls = new THREEa.OrbitControls(pCamera, pContainer);

【讨论】:

【参考方案8】:

在导入 THREE 后直接从源文件导入 OrbitControls 对我来说效果很好(不使用 three-orbitcontrols-ts 包):

import * as THREE from 'three';
import 'three/examples/js/controls/OrbitControls';

仅使用 three@types/three

【讨论】:

看起来这篇文章应该被标记为正确答案。 问题是在第一次导入之后THREE 是一个导入的对象,而不是three/examples/js/controls/OrbitControls 期望的窗口对象上的属性以便安装自己。 不适用于我的打字稿。 SyntaxError: Unexpected token 【参考方案9】:

我无法从这里得到任何东西,这篇文章实际上有效并且看起来一致或有足够的细节可以操作。希望这个答案可以为其他人提供一些见解。

在我的对象中,我已经通过使用类型提取三个 ts 文件进行了三个工作。这是很合理的,把ts文件放在typings/globals/three中。

以下是假设您已下载并安装 node.js 的步骤。这还会安装 npm(节点项目管理器),您可以从命令提示符运行它以执行以下所有步骤。

npm install typings --global
typings install dt~three --global --save

此时,一旦我将 ts 文件“包含”到我的对象中,所有基本的三种类型都可用:

/// <reference path="typings/globals/three/index.d.ts" />

此时没有定义OrbitControls,因为基本三包中没有包含它。但是,typings 数据库中有 ts 数据。所以我也安装了它:

typings install --globals three-orbitcontrols --save

它把 ts 文件放在这里:

node_modules\three-orbitcontrols-ts\dist\index.d.ts

我尝试了很多方法来让它工作,但我错过了一些东西。通常错误是未定义 THREE.OrbitControls。如果我删除了三个,那么它会生成不工作的 javascript

我最终做的我认为一种解决方法是编辑 typings/globals/three/index.d.ts 并将 typings/globals/three/OrbitControls/index.d.ts 的内容剪切并粘贴到 THREE 命名空间中结束。

在 OrbitControls/index.d.ts 的顶部,它调用 &lt;reference types="three" /&gt; 不起作用,因为在这种情况下它找不到“三”。一旦我解决了它,它编译但它生成了非工作代码。

【讨论】:

【参考方案10】:

不幸的是,以上答案都没有为我解决问题。我通过创建具有以下内容的three.js 文件找到了无需安装第三方软件包的解决方案:

import * as THREE from 'three';
window.THREE = THREE;
require('three/examples/js/controls/OrbitControls');

export default THREE;

然后import THREE from './three';

【讨论】:

【参考方案11】:

我在实施建议的解决方案时也遇到了一些不幸,因为它们都没有让 typescript 编译器满意。无法在编译时覆盖 THREE.OrbitControls,因为它被设置为只读。我的解决方案如下:

使用 npm 安装“三个”和“三个轨道控制”。 (这有点愚蠢但很有必要,因为'three'已经包含了examples/js/controls/OrbitControl.js文件中轨道控制的所有代码,但没有以打字稿理解的方式导出它。如果你不想要弄乱您的 3rd 方库,只需在“three”旁边安装“three-orbit-controls”,其中包含代码的副本,但以一种很好的方式导出它。

现在像下面这样使用它:

从'三'导入*作为三; 从“三轨道控制”导入 * 作为 OrbitControlsFunction; 常量 OrbitControls = OrbitControlsFunction(三); // OrbitControls 现在是你的构造函数 常量控件:THREE.OrbitControls = new OrbitControls(camera, element); // 从这里开始编写代码。

【讨论】:

【参考方案12】:

解决方案来自这个issue。 只需安装three-full 和@types/three 并将类型定义添加到tsconfig.json 中的“compilerOptions”。

  "compilerOptions": 
    /* ... */
    "baseUrl": ".",        // needed to use path aliases!
    "paths": 
      "three-full": ["node_modules/@types/three"]
  

然后导入三个就好了

import * as THREE from 'three-full';

之后一切正常,包括智能感知。

没有@types/three,`它仍然可以工作,但你不会得到智能感知。

【讨论】:

【参考方案13】:

如docs 中所述,请执行以下操作:

import * as THREE from 'three';
import  OrbitControls  from 'three/examples/jsm/controls/OrbitControls.js';

重要的是您使用文件夹jsm 而不是js。请记住,jsm 文件夹中并非所有模块都可用

【讨论】:

【参考方案14】:

如果您仍然希望从THREE 访问OrbitControls,以下似乎对我有用:

import * as __THREE from 'three';
import * as X from 'three/examples/jsm/controls/OrbitControls.js';

type THREE = typeof __THREE & typeof X

现在唯一真正的区别是,如果您指定控件的类型,它将看起来像

const controls: X.OrbitControls = new THREE.OrbitControls(camera, renderer.domElement)

【讨论】:

以上是关于在 TypeScript 中使用三个 Js + OrbitControls的主要内容,如果未能解决你的问题,请参考以下文章

在typescript项目中引入如何js依赖

在带有 TypeScript 的 Next.js 中使用 getInitialProps

如何在 TypeScript 中使用 three.js 加载 OBJ 模型

在 TypeScript 和 Next.js 中使用绝对导入解析模块

如何在 React.js Typescript 版本中使用不支持 typescript 的 javascript 包

Webpack 4,Vue 同时使用 Typescript 类和 JS 代码。