在 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 的顶部,它调用 <reference types="three" />
不起作用,因为在这种情况下它找不到“三”。一旦我解决了它,它编译但它生成了非工作代码。
【讨论】:
【参考方案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 的 Next.js 中使用 getInitialProps
如何在 TypeScript 中使用 three.js 加载 OBJ 模型
在 TypeScript 和 Next.js 中使用绝对导入解析模块