angulartypescriptx3d

Integrate Angular and X3D (render a simple box)


I am a complete newbie in web development, and I am completely lost.

I have downloaded the Angular Quickstart used in the Angular tutorial (https://github.com/angular/quickstart) and now I want to insert a simple x3d element. To do so, I have modified the files app.module.ts, app.component.ts and index.html.

The modified file app.module.ts is:

import { NgModule, NO_ERRORS_SCHEMA }      from '@angular/core';`
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  schemas:      [ NO_ERRORS_SCHEMA ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

The new app.component.ts that I have created is:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<x3d width='600px' height='400px'> 
                <scene> 
                    <shape>     
                        <appearance> 
                            <material diffuseColor='1 0 0'></material>
                        </appearance>       
                        <box></box> 
                    </shape> 
                </scene> 
             </x3d>`,
})
export class AppComponent  { name = 'Angular'; }

And finally, the new index.html looks like that:

<!DOCTYPE html>
<html>
  <head>
    <title>Angular QuickStart</title>
    <base href="/">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">

    <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>

    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script type='text/javascript' src='http://www.x3dom.org/download/x3dom.js'> </script> 

    <script src="systemjs.config.js"></script>
    <script>
      System.import('main.js').catch(function(err){ console.error(err); });
    </script>
  </head>

  <body>
    <my-app>Loading AppComponent content here ...</my-app>
  </body>
</html>

When I run $ npm start, nothing is shown, and the browser does not raise any errors, and I cannot figure out why. I am using Angular 4. Any help to solve this issue would be appreciated, thanks.


Solution

  • The problem is that X3D checks for x3d elements when the script loads and because you're loading an Angular component which holds the x3d element, X3D can not find your element. Unfortunately X3D does not provide such method to check the DOM for (new) x3d elements.

    I see that you're using Systemjs, you can use it easily load scripts during the load of your appcomponent. You will have to modify the configuration file for Systemjs and add an import statement in your component to load the X3D library. Best practice would be to load the library from the node modules. $ npm install --save x3dom

    Systemjs.config:

    (function (global) {
      System.config({
        paths: {
          // paths serve as alias
          'npm:': 'node_modules/'
        },
        // map tells the System loader where to look for things
        map: {
          // our app is within the app folder
          'app': 'app',
    
          // angular bundles
          ...
    
          // other libraries
          ...
          // load x3d from node modules
          ,'x3dom': 'npm:x3dom/x3dom.js'
        },
        // packages tells the System loader how to load when no filename and/or no extension
        packages: {
          ...
        }
      });
    })(this);
    

    To load the library with your component you can add an constructor to the class of the component and call an importstatement for x3d using Systemjs.

    App.component

    import { Component } from '@angular/core';
    
    // simple declaration to prevent the tscompiler from causing an compiling error
    declare var System : any;
    
    @Component({
      selector: 'my-app',
      template: `<x3d width='600px' height='400px'>
                    <scene>
                        <shape>
                            <appearance>
                                <material diffuseColor='1 0 0'></material>
                            </appearance>
                            <box></box>
                        </shape>
                    </scene>
                 </x3d>`,
    })
    export class AppComponent  {
      name = 'Angular';
      constructor() {
        System.import('x3dom')
          .then(() => {
            console.log('loaded');
          })
          .catch((e: any) => {
            console.warn(e);
          })
      }
    }
    

    Now everytime you bootstrap your app, Systemjs will try to import the x3dom library. And don't forget to remove the import of the x3dom library in your index.html, the library checks if window.x3dom already exists.