Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Cesium, SystemJS, and Angular2 to work?

Does somebody have a working example where SystemJS (not Webpack) is being used with an Angular2 (in TypeScript, not Dart) with Cesium (npm)?

I am aware of this blog post on cesiumjs' site: https://cesiumjs.org/2016/01/26/Cesium-and-Webpack/

And I like how the author says, "You can't simply do a require('cesium')." The problem with the article is that it uses the Webpack way, and I do not have that available.

Either way, I am looking to solve this particular error (from the Browser): Error: (SystemJS) AMD module http://localhost:3000/node_modules/cesium/Build/CesiumUnminified/Cesium.js did not define

Here's what I have:

In my systemjs.config.js file:

paths: {'npm:' :  'node_modules/'},
map: {
    // our app is within the dist folder
    app: 'dist',

    // angular bundles
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    ...

    'require': 'npm:requirejs/require.js',
    'cesium': 'npm:cesium/Build/CesiumUnminified/Cesium.js',

    // Other packages
    ...
}

@Injectable() Example:

let Cesium = require('cesium');
import { Injectable } from '@angular/core';

@Injectable()

export class CesiumClock {
    private _start:any = Cesium.JulianDate.now();
    private _stop:any = Cesium.JulianDate.addHours(this._start,12,new Cesium.JulianDate());
    private _clock:any = new Cesium.Clock({
        startTime: this._start,
        stopTime: this._stop,
        currentTime: this._start,
        clockRange: Cesium.ClockRange.LOOP_STOP,
        mutliplier: 1,
        shouldAnimate: true
    });
}

And finally, the client code that tries to use my 'CesiumClock', and gives me the error (after transpiling) in the browser:

import { Component } from '@angular/core';
import { CesiumClock } from '../services/index';

@Component({
    moduleId: module.id.replace("/dist", "/app"),
    templateUrl: 'stuff.component.html',
    styleUrls: [
        'stuff.css',
        'node_modules/cesium/Build/Cesium/Widgets/widgets.css'
    ]
 })

export class StuffComponent {
    constructor(private _cesiumClock:CesiumClock) {}
}

UPDATE:

Based on @artem's answer, I was able to remove the specific 'Error: (SystemJS) AMD' from the browser. But now, if I want to refer to anything Cesium, such new Cesium.Viewer(...) the Cesium object is just a blank slate. The error I see is

Cesium.Viewer is not a constructor

like image 767
westandy Avatar asked Nov 23 '16 20:11

westandy


2 Answers

Thanks to @artem for opening my eyes on this. Here's my final answer that works for me:

systemjs.config.js (See 'cesium' under packages and note the global variable, CESIUM_BASE_URL)

(function(global){
    global.CESIUM_BASE_URL = './node_modules/cesium/Build/CesiumUnminified';
    System.config({
        paths: {
            // paths serve as alias
            'npm:': 'node_modules/'
        },
        map: {
            ...
            // paths serve as alias
            'cesium': 'npm:cesium/Build/CesiumUnminified'
            ...
        },
        packages: {
            ...
            'cesium': {
                main: './Cesium.js',
                meta: {
                    '*.js': {
                        format: 'cjs'
                    }
                }
            },
            ...
        }
    });
})(this);

cesium.viewer.ts (Note the combined declare and import statements. The declare allows the typescript compiler to know about Cesium. The import statement is that it works in the browser.):

declare var Cesium:any;
import 'cesium';

@Injectable()
export class CesiumViewer {
    ...
    this._viewer = new Cesium.Viewer(elem, {...});
    ...
}

I believe, the meta part helps because Cesium actually needs a boatload of .js files. Without the meta *.js property, it only grabs Cesium.js, which is not enough, regardless of minification or not, Source or not.

Now, I've got a major CSS crisis. The Cesium map is a giant mess of junk in the browser.

like image 106
westandy Avatar answered Oct 14 '22 17:10

westandy


SystemJS auto-detects format for CesiumUnminified/Cesium.js as amd, but for whatever reason it does not work as amd module with SystemJS. It can be loaded if you set its format to CommonJS, that is:

    map: {
         ...
        'cesium': 'npm:cesium/Build/CesiumUnminified',

and

    packages: {
            ...
        cesium: {
            main: 'Cesium.js',
            format: 'cjs'
        },

Update it looks like SystemJS is unable to use both versions provided in node_modules/cesium/Build: mapping to either Cesium or CesiumUnminified in Build results in import Cesium = require('cesium'); returning an empty object.

However, it can be loaded from the sources provided in node_modules/cesium/Source. When I remove format: 'cjs' from cesium package and change mapping to 'cesium': 'npm:cesium/Source', I can get this code

 import Cesium = require('cesium');
 console.dir(Cesium.Viewer);

to print

 function Viewer(container, options)

in the console. No idea if it will actually work though.

like image 2
artem Avatar answered Oct 14 '22 18:10

artem