[英]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>
這是因為您試圖在外部腳本完全加載之前實例化地圖。 它在您的第一種情況下有效,但在直接刷新時不起作用。
這里發布了一個很棒的解決方案:
回調解決方案的問題在於您正在將外部腳本加載到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.