[英]Google Maps JavaScript API with lit-element
我正在嘗試使用使用 Google Maps API 的 lit-html 創建自定義元素。 如何讓它協同工作? 這是我到目前為止所擁有的:
地圖元素.css:
#map {
height: 400px; /* The height is 400 pixels */
width: 100%; /* The width is the width of the web page */
background-color: grey;
}
地圖-element.js:
import {
LitElement,
html
} from '@polymer/lit-element';
class MapElement extends LitElement {
render() {
return html `
<link rel="stylesheet" href="map-element.css">
<div id="map"></div>
<script>
function initMap() {
// The location of Uluru
var uluru = {lat: -25.344, lng: 131.036};
// The map, centered at Uluru
var map = new google.maps.Map(
this.shadowRoot.querySelector('#map'), {zoom: 14, center: uluru});
// The marker, positioned at Uluru
var marker = new google.maps.Marker({position: uluru, map: map});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=MYAPIKEY&callback=initmap">
</script>
`;
}
}
customElements.define('map-element', MapElement);
輸出只是帶有地圖 ID 的 div 的占位符,我沒有收到任何錯誤。
這是我嘗試在我的元素中使用的代碼的參考: https ://developers.google.com/maps/documentation/javascript/adding-a-google-map
您可以在connectedCallback
方法中添加腳本,以確保在組件包含在 DOM 中時包含它
constructor() {
this.callbackName = 'initMap';
this.mapsUrl = https://maps.googleapis.com/maps/api/js?key=MYAPIKEY
}
connectedCallback() {
window[this.callbackName] = this._initMap.bind(this)
this._addMapScript() // This
}
addScript: function() {
var script = document.createElement('script');
script.src = `${this.mapsUrl}&callback=${this.callbackName}`;
var s = document.querySelector('script') || document.body;
s.parentNode.insertBefore(script, s);
}
_initMap() {
// To be we have shadow DOM ready.
this.updateCompleted.then(this.initMap);
}
initMap() {
// Your code here
}
這樣的事情應該有效
Google Maps API 有一個非常嚴重的錯誤,它一直存在到頁面重新加載: https ://issuetracker.google.com/issues/35821412
這會在 SPA 和網絡組件框架(如 Lit)中產生問題,因為地圖不包含在組件中,它是由事件偵聽器附加到窗口的。
創建它很容易,但我要補充一點,您希望確保每頁僅加載一次 API,因此您需要某種已經加載過的全局日志。
像這樣:
/** URI of the Maps JS library */
const googleMapsApi = `https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places&callback=initMapApi`;
/** Flag indicating that mapping library is currently being loaded, wait for it to . */
let mapLoading = false;
/** Flag indicating that mapping library has been downloaded. */
let mapReady = false;
// Set window level function for maps API to call back to
(window as any).initMapApi = function () {
mapReady = true;
delete (window as any).initMapApi;
}
/** Call this before calling maps API methods to make sure that it's loaded.
* @returns {Promise<boolean>} True once loaded. */
export async function mapApiLoaded() {
if (mapReady)
return true;
while (mapLoading)
await new Promise(requestAnimationFrame);
if (mapReady)
return true;
try {
mapLoading = true;
// Get the API key for the current user
const google = // your key;
if (!google)
return;
const mapApiUri = googleMapsApi.replace('API_KEY', google);
// Add a <script> tag pointing to the API with the key
await new Promise((resolve, reject) => {
const script = document.createElement('script') as HTMLScriptElement;
script.type = 'text/javascript';
script.onload = resolve;
script.onerror = reject;
document.getElementsByTagName('head')[0].appendChild(script);
script.src = mapApiUri;
});
// Wait for the script to fire the callback method
while (!mapReady)
await new Promise(requestAnimationFrame);
console.log('🗺️ API loaded.');
}
finally { mapLoading = false; }
return mapReady;
}
一旦你有了它,你就可以在每個地圖組件的firstUpdated
或connectedCallback
中調用它。
但是,由於內存泄漏,如果您創建大量此類地圖並擁有單頁應用程序,您將很快遇到問題 - 您傳遞給new google.maps.Map
的每個元素都會附加到窗口,直到用戶刷新,並且沒有辦法斷開它。
您仍然可以將 Google Maps API 與 SPA 一起使用,但您必須重新使用地圖實例......
connectedCallback
上檢查現有地圖元素並在未連接時重新使用。disconnectedCallback
上清除路由/標記/等並緩存地圖以供重用。所以你的代碼最終是這樣的:
@customElement('map-element')
class MapElement
extends LitElement {
render() {
return html `<div id="map"></div>`;
}
@query('#map')
private mapWrapper: HTMLDivElement;
private map: google.maps.Map;
async connectedCallback() {
await mapApiLoaded();
const oldMap = window.oldMaps.pop() // Or however you get your previously used maps
if (!oldMap)
// Create new map in your wrapper
this.map = new google.maps.Map(this.mapWrapper, ...your options);
else {
// Reconfig old map and add it to your wrapper
oldMap.setOptions(...your options);
this.map = oldMap;
this.mapWrapper.appendChild(oldMap);
}
}
disconnectedCallback() {
if(!this.map) return;
// Remove from shadow DOM
this.map.remove();
// Clear markers/routes from this.map
// Add to register of unused maps, say...
window.oldMaps.push(this.map);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.