THREE.js webGL rendering works w "ionic serve", but not for iOS xcode build

I’m building an app for iOS (must be built using xcode), that sets up and renders a webGL scene using THREE.js. Running with ionic serve everything works well in Chrome, and everything is rendered well when using DevApp on iphone 8plus running iOS 11.4. However, when I build using ionic cordova build ios --prod and then use xcode to install onto the same iPhone, the app just shows a blank white screen.

I’m using pretty much the latest version of everything:

    @ionic/cli-utils  : 1.19.2
    ionic (Ionic CLI) : 3.20.0
    cordova (Cordova CLI) : 8.0.0 
    @ionic/app-scripts : 3.1.10
    Cordova Platforms  : ios 4.5.4
    Ionic Framework    : ionic-angular 3.9.2
    Node  : v8.11.3
    npm   : 5.6.0 
    OS    : macOS High Sierra
    Xcode : Xcode 9.4.1 Build version 9F2000
    iOS: 11.4

I’ve installed the official three.js npm package, using the command npm i three, as well as three-orbit-controls and three-decal-geometry. The code is not doing anything too advanced, just importing JSON geometry, creating meshes from the geometry, applying a texture, and then rendering and providing camera control.

In my code, I load a directive that gets passed element reference of the parent, and appends the THREE.js renderer’s DOM element to the parent, as follows:

  • in the directive:
       import { Directive, ElementRef, Input } from '@angular/core';
       ....other imports and requires....

       @Directive({ selector: 'cubeCanvas' })
       export class CubeCanvasDirective {

           constructor(el: ElementRef) {
               this.el = el;

           init() {
               ...THREE setup (cameras, controls, scenes, etc)...
               this.renderer = new THREE.WebGLRenderer();

           render = () => {
               ...basic updates to controls and light....
  • in page’s typescript file:
    import { Component, ViewChild } from '@angular/core';
    ...other imports and requires...

       selector: 'page-standard',
       templateUrl: 'standard.html'
    export class StandardPage {  

      @ViewChild(CubeCanvasDirective) vc:CubeCanvasDirective;
      ...other members...

      constructor(public navCtrl: NavController, 
                  public navParams: NavParams,
                  public cubeStateProvider: CubeStateProvider) { 
    } I can call directive's functions using    
  • I then insert the directive into page’s html using <cubeCanvas></cubeCanvas>

Am I attaching the renderer to the DOM incorrectly? Is there something wrong with the packages I’m using? Any other ideas on what could be going wrong?

1 Like

An update, for any interested parties:

I have found at least one issue with a certain THREE.js package and one ionic related issue (specifically when using on iOS). However, none of the issues are with the code I included above, and the issue is not related to the official THREE.js core library port to npm. This is what was causing my issues:

  1. The scene was not rendering because filepath to the assets folder are slightly different when built for iOS instead of run with ionic serve. See this THIS THREAD for details.

  2. For some reason, three-orbitcontrols package (which has been recently updated and claims to be from the official repo), causes the webGL scene to steal context from ionic UI or something (I’m sure my terminology is way off). Basically, when any scene that uses that package to include OrbitControls in the scene, ionic components stop working (buttons, menus, etc). However, using the same exact code with three-orbit-controls package (literally a direct drop in replacement), solves all the issues and provides the desired OrbitControls. The issues did not show up when accessing ionic served page on PC, but it did anytime using iOS. I only tested with iPhone running iOS 11.4, but the issue is there regardless of if you use Devapp, iOS chrome browser, or if built with ionic cordova build ios.