Using Threejs + OrbitContols in TypeScript
Asked Answered
B

16

19

I'm not able to get this example of using the aforementioned combo going in TypeScript.

I have <script src="lib/three.min.js"></script> and <script src="lib/OrbitControls.js"></script> in my html <head> and the typescript file in <body>:

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

and

this.controls.update();

in periodically called render() function. For all I know, the setup is identical to the expample, but gives me a huge error (abbreviated) on compilation of the OrbitControls constructor line:

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

I guess there's whole Threejs in that error, since Visual Studio crashes the moment I click on it :). Thanks for your help.

Binghi answered 18/10, 2013 at 8:5 Comment(0)
B
1

Feeling kind of silly since the solution (or workaround at least) turns out to be quite simple...

Just declare the OrbitControls variable:

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

There are still some compilation errors but it works.

Binghi answered 21/10, 2013 at 9:22 Comment(2)
I don't think this is a good idea. You should try to avoid using any to bypass typescript issues. It's a band-aid that will fall off.Predicable
@JuanSolano I agree, my "solution" is definitely temporaryBinghi
S
27

As described in the docs do the following:

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

Important is that you use the folder jsm instead of js. And keep in mind that not all modules are available in the jsm folder yet

Sprague answered 28/5, 2019 at 9:20 Comment(0)
S
19

After few hours spend on this problem, I ended up creating a new package: three-orbitcontrols-ts

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

const controls = new OrbitControls(camera, renderer.domElement);
Springing answered 7/1, 2017 at 10:34 Comment(3)
Has anyone found something like this but for the trackball controls?Thailand
Great work, but now we have another package to get out of sync. For instance, this package is already missing the saveState routine which is used by some other components I am using.Epicurean
This answer is outdated : since then, threejs proposes proper js modules, see https://mcmap.net/q/628403/-using-threejs-orbitcontols-in-typescriptUnearned
M
8

Importing the OrbitControls directly from the source file after importing THREE worked great for me (without using the three-orbitcontrols-ts package):

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

Using only the three and @types/three packages

Manifesto answered 23/2, 2017 at 19:4 Comment(3)
looks like this post this should be marked as correct answer instead.Boutique
The problem is that after the first import THREE is an imported object, not a property on the window object as three/examples/js/controls/OrbitControls expects in order to install itself.Epicurean
Does not work with typescript for me. SyntaxError: Unexpected token {Mercuric
T
4

Unfortunately none of above answers solved problem for me. I have found solution without installing third party packages by creating three.js file with below content:

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

export default THREE;

and then import THREE from './three';

Toro answered 6/10, 2018 at 23:4 Comment(0)
I
3

While previous answers may work out to some degree, you should go with the ready made definition files from DefinitelyTyped. They also define OrbitControl's properties and methods.

Imbecilic answered 2/12, 2014 at 4:48 Comment(3)
the link is brokenKurgan
Sorry, here is the updated link: github.com/DefinitelyTyped/DefinitelyTyped/blob/master/three/…Imbecilic
This does not answer the question of how to bring in OrbitControls themselves.Epicurean
B
1

Feeling kind of silly since the solution (or workaround at least) turns out to be quite simple...

Just declare the OrbitControls variable:

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

There are still some compilation errors but it works.

Binghi answered 21/10, 2013 at 9:22 Comment(2)
I don't think this is a good idea. You should try to avoid using any to bypass typescript issues. It's a band-aid that will fall off.Predicable
@JuanSolano I agree, my "solution" is definitely temporaryBinghi
M
1

I tried some of the suggested solutions and could not get it to work right so after some experimentation, I ended up with:

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

I am using webpack bundling and with this I did not have to add the script tag in the HTML template.

Molybdic answered 22/12, 2016 at 21:29 Comment(0)
S
1

If you actually still want OrbitControls to be accessed from THREE, the following seems to work for me:

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

type THREE = typeof __THREE & typeof X

Only real difference is now if you specify the type of controls, it'll look something like

const controls: X.OrbitControls = new THREE.OrbitControls(camera, renderer.domElement)
Shoddy answered 5/2, 2021 at 4:19 Comment(0)
G
1

In 2024 with a recent version of three.js i had to add:

    "typeRoots": ["node_modules/@types"]    

to my tsconfig.json

Gariepy answered 9/6 at 23:14 Comment(0)
K
0

The answer didn't work for me in eclipse typescript, since it conflicted with the reference statement earlier. But the following works:

declare module THREE {export var OrbitControls}
Kela answered 11/2, 2014 at 5:16 Comment(0)
M
0

After adding the three-orbitcontrols typings and three-orbit-controls npm package (why aren't these named the same?), I was still having issues getting it to work in Typescript. This ended up working for me in case it's helpful for anyone else who doesn't want to use the workaround:

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);

As of today, it seems that the OrbitControls npm package is using an old style of exports that requires an old-style require statement that passes in the Three library.

Method answered 13/7, 2016 at 22:2 Comment(0)
M
0

outside ts:

var THREEa = THREE;

inside ts:

var controls = new THREEa.OrbitControls(pCamera, pContainer);
Mirthamirthful answered 8/1, 2017 at 14:0 Comment(0)
K
0

I was not able to get anything from here this post actually worked and seemed consistent or had enough detail to be actionable. Hopefully, this answer might provide some insight to others.

In my objects I already had three working by using typings to extract the THREE ts file. This was very reasonable and put the ts file in typings/globals/three.

Here are the steps assuming that you have downloaded and installed node.js. This also installs npm (Node Project Manager) which you can run from a command prompt to so all the steps below.

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

At this point all the basic THREE types are available once I "include" the ts file in my object:

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

At this point OrbitControls is not defined because the basic three package does not include it. However, there is ts data in the typings database. So I installed it as well:

typings install --globals three-orbitcontrols --save

It puts the ts file here:

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

I tried a number of things to get it to work but I am missing something. Generally the error was that THREE.OrbitControls was not defined. If I removed the THREE then it generated non-working JavaScript.

What I finally did which I consider a workaround is edit typings/globals/three/index.d.ts and cut and pasted the contents of typings/globals/three/OrbitControls/index.d.ts into the THREE namespace at the end.

At the top of the OrbitControls/index.d.ts it calls out <reference types="three" /> which doesn't work because in that context it cannot find "three". Once I worked around that it compiled but it generated non-working code.

Kreg answered 17/5, 2017 at 19:0 Comment(0)
E
0

I've also had some bad luck implementing the suggested solutions as none of them made the typescript compiler happy. Couldn't overwrite THREE.OrbitControls at compile time because it was set to read-only. My solution was as follows:

Install both 'three' and 'three-orbit-controls' with npm. (This is kinda dumb but necessary since 'three' already contains all the code for the orbit controls in the examples/js/controls/OrbitControl.js file but doesn't export it in a way that typescript understands. If you don't want to mess with your 3rd party libraries, just install 'three-orbit-controls' alongside 'three' which contains a duplicate of the code but exports it in a nice way.

Now use it like below:

import * as THREE from 'three';
import * as OrbitControlsFunction from 'three-orbit-controls';
const OrbitControls = OrbitControlsFunction(THREE); // OrbitControls is now your constructor
const controls: THREE.OrbitControls = new OrbitControls(camera, element); // Code as you would from here on out.

Europeanize answered 12/11, 2018 at 17:5 Comment(0)
U
0

The solution is from this issue. Just install three-full and @types/three and add the types definitions to "compilerOptions" in tsconfig.json.

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

Then import THREE like

import * as THREE from 'three-full';

Afterwards everything works fine including intellisense.

Without @types/three,` it still works, but you do not get intellisense.

Unmannerly answered 11/3, 2019 at 23:29 Comment(1)
three-full is deprecated, the github README says : "I am glad to annonce since Three release his examples files under JSM folder, this repository should be avoided."Unearned
S
0

The best solution that I have found is to copy/paste the OrbitControls.ts file to my projects: https://github.com/pmndrs/three-stdlib/blob/main/src/controls/OrbitControls.ts

Suburb answered 4/6 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.