I am using the elf example that is a standard example with ThreeJS
Instead of the rotation shown in the example I want to move the object in both the x and y direction. This should be achievable by changing elf.position.x
and elf.position.y
in the init() function.
This issue I am facing it that I created an object(class) of the methods that create an elf so I can create multiple ones. I also have a function that should move the object over time. var e
is not accessible in the move function. When I change it to this.e
and I change this e = collada.scene;
to this.e = collada.scene;
I get the following error: Uncaught TypeError: Cannot set property 'e' of undefined
Code:
class DrawElf {
constructor(scene) {
var e;
this.loadingManager = {};
this.loader = {};
this.scene = scene;
// loading manager
this.loadingManager = new THREE.LoadingManager(function () {
scene.add(e);
});
// collada
this.loader = new THREE.ColladaLoader(this.loadingManager);
this.loader.load('./models/collada/elf/elf.dae', function (collada) {
e = collada.scene;
e.scale.set(30, 30, 30);
e.position.set(100, 10, 100);
e.name = "elf.dae" + 0 + 0;
e.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.name = e.name;
ToIntersect.push(child);
}
});
});
}
move(time) {
// i want to move the object
}
}
Hopefully someone can help out.
I've edited your example code to show how to access the elf model in the move()
function and called out the changes in comments below.
class DrawElf {
constructor(scene) {
// Change 1: Place the `e` variable on `this` so it's accessible
// from member functions like `move`
this.e = null;
this.loadingManager = {};
this.loader = {};
this.scene = scene;
// Change 2: Use arrow functions instead so that the scope of the
// constructor is retained in the callback and `this` still references
// the new `DrawElf` instance
// collada
this.loader = new THREE.ColladaLoader();
this.loader.load('./models/collada/elf/elf.dae', (collada) => {
this.e = collada.scene;
this.e.scale.set(30, 30, 30);
this.e.position.set(100, 10, 100);
this.e.name = "elf.dae" + 0 + 0;
this.e.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.name = this.e.name;
ToIntersect.push(child);
}
});
// Change 3: Remove the loading manager because it's not needed to
// add the elf to the scene and instead do so here
scene.add(this.e);
});
}
move(time) {
// Change 4: Check if the scene has been loaded before trying to move
// the model
if (this.e) {
// move the model here
}
}
}
The big change here is to use arrow functions instead of the original Javascript functions so this
still references the object instance being constructed. This SO answer should explain the differences in scoping a bit more.
Hopefully that helps! Let me know if anything is unclear.