簡體   English   中英

如何在Aurelia中使用BingMaps

[英]How to use BingMaps with Aurelia

我正在為我的應用程序使用aurelia骨架打字稿webpack模板。 我想將BingMaps添加到頁面並能夠添加圖釘等。到目前為止,我已經做到了:

index.html-我添加了一個腳本標記,可從CDN加載地圖

<head>
...
   <script type='text/javascript' src='http://www.bing.com/api/maps/mapcontrol'></script>
</head>

然后我添加了這樣的模板:

map.html

<template>
   <div id='mainMap' style='width: 100vw; height: 100vh;'></div>
</template>

然后我有地圖控制器:

map.ts

export class Map {

    private map: Microsoft.Map.Map;

    attached() {
        this.map = new Microsoft.Maps.Map('mainMap', { credentials:'mycredentials - omitted'});
        ...
    }
}

現在,如果我啟動該應用程序,則將顯示歡迎屏幕(從框架開始)。 然后,我點擊“地圖”菜單鏈接,顯示地圖頁面並加載了完整的地圖。 但是,如果我在瀏覽器中單擊“刷新”(F5或Ctrl + F5),地圖將不再顯示,並且控制台中將顯示錯誤:

bluebird.js:1546未處理的拒絕TypeError:無法讀取位於h( https://www.bing的 k( https://www.bing.com/mapspreview/sdk/mapcontrol:11:7096 )為null的屬性'prototype' 的.com / mapspreview / SDK /地圖控件:11:6285 )在E( https://www.bing.com/mapspreview/sdk/mapcontrol:11:1106 )在t1 [按實例]( https://www.bing在h( https://www.bing.com/mapspreview/sdk/mapcontrol:11:6042 )在e( https://www.bing.com/mapspreview的 .com / mapspreview / sdk / mapcontrol:11:161/ sdk / mapcontrol:11:1106 ),位於tl [作為實例]( https://www.bing.com/mapspreview/sdk/mapcontrol:11:161 ),位於新的Microsoft.Maps.Map( https:// www。 bing.com/mapspreview/sdk/mapcontrol:13:4304 )位於Map.attached( http:// localhost:9000 / app.bundle.js:31267:20 )at Controller.attached( http:// localhost:9000 /在ViewSlot.attached( http:// localhost:9000 / aurelia.bundle )的View.attached( http:// localhost:9000 / aurelia.bundle.js:4524:23 )處的aurelia.bundle.js:6438:22。 js:4883:13 )在View.attached( http:// localhost:9000 / aurelia.bundle.js:4 534:19 )在ViewSlot.attached( http:// localhost:9000 / aurelia.bundle.js:4883:13 )在http:// localhost:9000 / aurelia.bundle.js:14717:28

當試圖在地圖控制器的Attached事件中實例化Map對象時,拋出此錯誤。

為什么會發生這種情況,我該如何解決? 請幫忙

謝謝

解決此問題的關鍵是使用API​​允許我們在腳本url中指定的callback參數。 我創建了一個自定義元素來執行此操作。 最初加載模塊時將加載腳本。 custom元素的任何實例都將等待回調函數被調用。 我最初使用的是帶有MutationObserver和data屬性的復雜設置,但是在與Jeremy Danyow交談之后,他指出“ Promisifying”回調將更簡單地解決該問題。 這種更簡單的解決方案如下所示。

除了獲取地圖的當前中心點之外,自定義元素目前不提供任何與地圖進行交互的API,但這是幫助您的一個很好的起點。

炳map.ts

import { bindable, bindingMode, inlineView } from 'aurelia-framework';

const controlUrl = '//www.bing.com/api/maps/mapcontrol?callback=bingMapsLoaded';
const ready = new Promise(resolve => window['bingMapsLoaded'] = resolve);

let scriptTag: HTMLScriptElement = document.createElement('script');

scriptTag.async = true;
scriptTag.defer = true;
scriptTag.src = controlUrl;

document.head.appendChild(scriptTag);

@inlineView('<template><div ref="container" css="width: ${width}; height: ${height};"></div></template>')
export class BingMapCustomElement {
  private container: HTMLElement;
  private map: Microsoft.Maps.Map;
  private viewChangeHandler: Microsoft.Maps.IHandlerId;

  @bindable apiKey = '';
  @bindable height = '600px';
  @bindable width = '400px';

  @bindable({ defaultBindingMode: bindingMode.twoWay }) location: Microsoft.Maps.Location | string;

  attached() {
    return ready.then(() => {
      this.map = new Microsoft.Maps.Map(this.container as HTMLElement, {
        credentials: this.apiKey
      });

      this.location = this.map.getCenter();

      this.viewChangeHandler = Microsoft.Maps.Events.addHandler(this.map, 'viewchange', e => {
        this.location = this.map.getCenter();
      });
    });
  }

  detached() {
    if (this.viewChangeHandler) {
      Microsoft.Maps.Events.removeHandler(this.viewChangeHandler);
    }

    if (this.map) {
      this.map.dispose();
      this.map = null;
    }
  }
}

用法

<bing-map api-key.bind="mapsApiKey" width="100px" height="100px"></bing-map>

這是因為您試圖在外部腳本完全加載之前實例化地圖。 它在您的第一種情況下有效,但在直接刷新時不起作用。

這里發布了一個很棒的解決方案:

如何等待BingMaps在Aurelia中加載

回調解決方案的問題在於您正在將外部腳本加載到index.html中,而這對於您當前是否要顯示地圖是無視的。 所以第二種解決方案更合適。 但是,我認為該解決方案是為ESNext代碼編寫的,並且您使用的是TypeScript,這意味着typeof屬性永遠不會是不確定的。 以下map.ts的代碼在您的上下文中會更好地工作(由於我無法對其進行測試,您可能需要對其進行一些調試):

export class Map
{
  map:Microsoft.Maps.Map;

  attached() {
    this.loadMap();
  }

  loadMap() {
    if ((Microsoft == null) || (Microsoft.Maps == null)) {
      // not yet available, keep trying (dirty checking)
      setTimeout(this.loadMap, 100);
    } else {
      // Map API available; proceed to render the map
      this.map = new Microsoft.Maps.Map('#mainMap', {credentials: myKey});
      this.map.setView({center: new Microsoft.Maps.Location(45.093,14.114), zoom:15});
    }
  }
}

請注意if ((Microsoft == null) || (Microsoft.Maps == null))測試,而不是undefined測試。

另一個出色的解決方案(Jason Sobell撰寫)

http://www.sobell.net/calling-external-javascript-from-within-aurelia-templates/

第三大解決方案(經過一些回調研究)

您可以在index.html 使用外部腳本鏈接的情況下實現此功能,因為這應動態提供加載機制。

export class Map
{
  private map: any;

  attached() {
    this.loadScript("//www.bing.com/api/maps/mapcontrol?onload=callback");
  }

  loadScript(sScriptSrc) {
    var oHead = document.getElementsByTagName("head")[0];
    var oScript = document.createElement('script');
    oScript.type = 'text/javascript';
    oScript.src = sScriptSrc;
    oHead.appendChild(oScript);
    oScript.onload = this.loadMap();
  }

  loadMap() {
    // Map API available; proceed to render the map
    this.map = new Microsoft.Maps.Map('#mainMap', {credentials: myKey});
    this.map.setView({center: new Microsoft.Maps.Location(45.093,14.114), zoom:15});
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM