让Cesium、SystemJS和Angular2一起工作?

6

有没有人有一个使用SystemJS(而不是Webpack)与Angular2(TypeScript而不是Dart)和Cesium(npm)一起使用的工作示例?

我知道这篇关于cesiumjs网站的博客文章: https://cesiumjs.org/2016/01/26/Cesium-and-Webpack/

我喜欢作者说的话:“你不能简单地做一个require('cesium')。”文章的问题在于它使用了Webpack的方式,而我没有那个可用。

无论如何,我想解决这个特定的错误(来自浏览器): Error: (SystemJS) AMD模块http://localhost:3000/node_modules/cesium/Build/CesiumUnminified/Cesium.js未定义

这是我的代码:

在我的systemjs.config.js文件中:

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() 示例:

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
    });
}

最后,客户端代码尝试使用我的“CesiumClock”,并在浏览器中转译后给我错误:

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) {}
}

更新

根据@artem的答案,我成功从浏览器中删除了特定的“错误:(SystemJS)AMD”。但是现在,如果我想引用任何Cesium内容,例如new Cesium.Viewer(...)Cesium对象就像一个空白的画布一样。我看到的错误信息是:

Cesium.Viewer不是一个构造函数


抱歉打断一下,但是对于未来的观众。只需使用 https://github.com/tgftech/angular-cesium - davidyaha
3个回答

4
感谢 @artem 让我茅塞顿开。这是适合我的最终答案:
systemjs.config.js中(参见packages下的'cesium',并注意全局变量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(请注意联合的declareimport语句。声明让TypeScript编译器了解关于Cesium的信息,而导入语句则确保在浏览器中正常工作。):

declare var Cesium:any;
import 'cesium';

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

我相信,meta部分的作用在于Cesium实际上需要大量的.js文件。 如果没有meta *.js属性,它只会获取Cesium.js,无论是否经过了最小化处理,无论是否是源代码。

现在,我遇到了重大的CSS危机。 在浏览器中,Cesium地图看起来一团糟。


目前对我来说还不起作用 :-/ 我收到了错误 EXCEPTION: Uncaught (in promise): Error: Error in :0:0 caused by: Unable to process binding "click: function (){return function(){ cameraClicked.raiseEvent(this);} }" Message: n(...).bind is not a function TypeError: Unable to process binding "click: function (){return function(){ cameraClicked.raiseEvent(this);} }" Message: n(...).bind is not a function 有什么想法吗? - mfreiholz
@mfreiholz - 我认为你可能有一个单独的问题。我会发布一个问题,如果你认为它有帮助,可以在设置方面链接这个问题?如果我们的问题是重复的,肯定会有人注意到的。 - westandy

2

SystemJS会自动检测CesiumUnminified/Cesium.js的格式为amd,但由于某些原因,它无法作为SystemJS中的amd模块工作。如果您将其格式设置为CommonJS,则可以加载它,即:

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

并且

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

更新:看起来SystemJS无法同时使用node_modules/cesium/Build中提供的两个版本:在Build中映射到CesiumCesiumUnminified会导致import Cesium = require('cesium');返回一个空对象。

然而,它可以从node_modules/cesium/Source中提供的源代码加载。当我从cesium包中删除format: 'cjs'并将映射更改为'cesium': 'npm:cesium/Source'时,我可以获得这段代码。

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

打印

 function Viewer(container, options)

在控制台中尝试。不知道是否实际可行。


我本想给你打个勾,但直到今天我才有机会测试它。谢谢! - westandy
所以,这解决了我遇到的错误,但它并没有让我在我的@Components中使用Cesium。Cesium.Viewer未定义,Cesium.someFunctionThatIsDefined不是一个函数。 - westandy
是的,BuildCesium.js 的格式对我来说并不熟悉,我不确定它是否被 SystemJS 支持。但是,我可以从 node_modules/cesium/Source 加载已填充的 cesium 对象,不知道它有多有用。我已更新答案。 - artem

0

我通过使用稍微不同的配置使Cesium与Angular 2和SystemJS配合工作,因为上面的答案对我没有用。

systemjs.config.js:

(function (global) {
  global.CESIUM_BASE_URL = './node_modules/cesium/Build/CesiumUnminified';
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
     ...
     'cesium': 'npm:cesium/Build/CesiumUnminified'
     ...
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
  ...
  'cesium': {
    main: './Cesium.js',
    meta: {
      '*.js': {
        format: 'global'
      }
    }
  }
}
});
})(this);

还有在 app.component.js 中的这段代码:

import 'cesium';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接