I'm trying to achieve a pretty basic animation using ThreeJS in my Ionic 2 application. Basically trying to rotate a cube. But the cube isn't rotating because requestAnimationFrame is being executed only once inside the render loop.
No rotating animation. I'm sharing my code below.
home.html
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<div #webgloutput></div>
</ion-content>
home.ts
import { Component, ViewChild, ElementRef } from '@angular/core';
import { NavController } from 'ionic-angular';
import * as THREE from 'three';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
@ViewChild('webgloutput') webgloutput: ElementRef;
private renderer: any;
private scene: any;
private camera: any;
private cube: any;
constructor(public navCtrl: NavController) {
}
ngOnInit() {
this.initThree();
}
initThree() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize( window.innerWidth, window.innerHeight );
this.webgloutput.nativeElement.appendChild(this.renderer.domElement);
let geometry = new THREE.BoxGeometry(1, 1, 1);
let material = new THREE.MeshBasicMaterial({ color: 0x00ff00});
this.cube = new THREE.Mesh(geometry, material);
this.scene.add(this.cube);
this.camera.position.z = 5;
this.render();
}
render() {
console.log("render called");
requestAnimationFrame(() => this.render);
this.cube.rotation.x += 0.5;
this.cube.rotation.y += 0.5;
this.renderer.render(this.scene, this.camera);
}
}
The problem is that you are not calling your requestAnimationFrame correctly. You are not passing it the render function directly, but instead a lambda function that returns the render function.
Change the line
requestAnimationFrame(() => this.render);
torequestAnimationFrame(this.render);
Edit:
When using ES2015 classes like you are, it is important to remember that class methods are functions that are declared as object properties. The context (this) will be the object that the method is attached to. So when passing the method to the
requestAnimationFrame(...)
method, it will no longer be called with the same object reference. Because of this, we need to bind the context of the render method before passing it to therequestAnimationFrame(...)
:This is expained well in this blog post. (don't mind that it is focused on React, the principles and examples are ES2015 specific).