RequestAnimationFrame is called only once

I am trying to achieve a fairly simple animation using a ThreeJS app in my Ionic 2 app. Basically trying to rotate a cube. But the cube doesn't rotate because requestAnimationFrame is executed only once inside the render loop.

I can only see this. enter image description here

No rotating animation. I am 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);
  }

}

      

+3


source to share


1 answer


The problem is you are calling your requestAnimationFrame incorrectly. You are not passing it directly to the render function, 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, it's important to remember that class methods are functions declared as properties of an object. The context (this) will be the object that the method is bound to. Therefore, by passing a method to a method requestAnimationFrame(...)

, 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 requestAnimationFrame(...)

:

requestAnimationFrame(this.render.bind(this));

      

This has been preserved well in this blog post . (don't remember it is React oriented, principles and examples are ES2015 specific).

+5


source







All Articles