Hello, I have searched and searched, I have done many tests but I still cannot, through a script executed by a button click, change the values of the rotation and position of the camera. It happens that OrbitControls always resets the new values to the last ones I was using. I also found a script called camera-controls (https://github.com/yomotsu/camera-controls - works as script and uses threejs as script) that does everything I need but it is not written as a module and I have not managed to integrate it into the new threejs. Does anyone know how to integrate “camera-controls” module with threejs module?
One way you could do it is emit custom MouseEvent
events, so to emulate a user dragging on the screen in the same way that you wish to animate the controls.
For example, for each animation frame,
const mouseEvent = {
button: 0,
clientX: 0,
clientY: 0,
movementX: 0,
movementY: 0,
relatedTarget: null,
screenX: 0,
screenY: 0,
}
const mouseEventPlusOne = {
button: 0,
clientX: 1,
clientY: 1,
movementX: 1,
movementY: 1,
relatedTarget: null,
screenX: 1,
screenY: 1,
}
// emulates a 1-pixel drag from `0,0` to `1,1`
// run this once, at the beginning of the animation loop
this.renderer.domElement.dispatchEvent(new MouseEvent('pointerdown', mouseEvent))
// run something like this on each animation frame
document.dispatchEvent(new MouseEvent('pointermove', mouseEventPlusOne))
// run this at the end of the animation loop
document.dispatchEvent(new MouseEvent('pointerup', mouseEventPlusOne))
You’d first dispatch a pointerdown
event, then each animation frame dispatch a pointermove
event, and finally after the fake “drag” is complete dispatch a pointerup
event.
You can calculate the numbers to “drag” with for each frame using a lib like tween.js
:
Or, to keep it simple, you could simply increment the numbers on each frame.
Also, if you study OrbitControls
code, you could also figure another way to do it by doing something similar to what OrbitControls
does, but instead of emulating user events you would modify the camera positioning the same way that OrbitControls
does.
Oh it is true that solution did not occur to me and I see it perfectly effective. What I do not understand is why they do not add new functions to perform this task to the OrbitControl module because I have seen many people trying to do similar things but as this module resets the information passed through the script it does not work. It would be great if you could add these new features.
On the other hand, it would also be good to give the “camera-control” script a spin because it works perfect but it does not work as a module so it cannot be used with the new versions of threejs. At least until what I have seen I have not found a way to pass it to module.
Thanks a lot trusktr !!! I will follow your advice.
Would be great for someone to make a PR if they’re interested enough to implement it. No guarantee they’ll accept it though. If someone of the team says they would, then it will be worth trying to implement it.
Not exactly sure what you mean by that part. Can you expand on that?
No prob!
Of course, what I am trying to explain is that this “camera-control” script was created as a javascript script and not as a javascript ES6 module. I have done some research on this to see if I can convert it as a module or if it is possible to use this javascript script and the threejs modules together.
I’m still researching how to pass a normal javascript script to module. I think it would be the best option.
@Darkladen I’m still not completely clear as to what you’re trying. I mean, I understand that a regular script (that does not export anything) does not leave anything for an ES Module to import
. But regardless of that, the script file will still be executed when it is import
ed.
This OrbitControls.js file is an ES Module.
Were you perhaps trying to load the other one, which is not an ES Module?
Note one has js/
in the path, while the other has jsm/
in the path (m for “modules”). In practice, you’d import it like this:
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
@trusktr I think I should have started this whole thread, saying that I am studying the differences between a simple javascript script and an ES Module. The issue is that I was trying to mix the “camera-control” script with the threejs ES Module because I had read that the versions of Threejs in traditional script format would be obsolete but now seeing what you tell me about the JS and JSM folders I see that they are both versions updated although in the JS folder there are not all the same modules as in JSM and this is why maybe I should keep trying to mix JS and JSM for the same project but as I said, I can’t get both types to work together But I’ll keep looking Now if I could pass the “camera-control” script to ES Module everything would be easier. Thanks for your time.

JS folder there are not all the same modules as in JSM
Can you point to an example? I thought that the js/
folder was auto-generated from the jsm/
folder.

I can’t get both types to work together
Yeah, the scripts and modules are not designed to work together like that out of the box. But you can do make it work with some manual steps.
First, write an entry point like this:
import './make-three-global.js'
import './path/to/three/examples/js/controls/OrbitControls.js' // any non-JSM file that depends on `THREE` global.
console.log(THREE.OrbitControls) // <-- this works.
Then, in make-three-global.js
you need to do something like this:
import * as THREE from 'three'
// This creates a global `THREE` variable
// We're making a new object here, so that it can be extended by other code (because
// import objects from an import statement are non-extensible and trying to add any new
// properties to such an object will throw a runtime error)
window.THREE = {...THREE}
Now, because you entry point will next import the OrbitControls.js
file, a THREE
global variable will have already been created so therefore the OrbitControls.js
file will be able to successfully add a new OrbitControls
property to that THREE
object.
Then the console.log
statement in the entry point will work (or anything like new THREE.OrbitControld
will work).
However, I don’t think you need to do that if all js
files exist also as jsm
files. But if in fact this is true, that js/
has some classes that jsm
/ does not, then the above is how you can make it work.
@Darkladen Actually, its backwards: the jsm/
files are auto-generated from the js/
files, as it states in CONTRIBUTING.md
:
- If you modify files in
examples/js
directory, then don’t perform any changes in theexamples/jsm
, JavaScript modules are auto-generated via runningnode utils/modularize.js
.
So anything that is in js/
must be in jsm/
, otherwise it is a bug.
If there is such a case, please report that to the three.js issue tracker.
thank you very much @trusktr for your help,
I will follow your advice.
Dear, finally using threejs scripts (and not module) I was able to combine with the “camera -controls” script and everything works as expected. It is quite fluid and works well. I think this is the solution/option for those who expect to add extra functions in “OrbitControls”.
The only thing missing from the “camera-controls” script is that they can release a module version. I will continue investigating on this point.
Thanks @trusktr for the guidance and help.