我有一个单独的 label.js 文件,我在其中定义了自定义叠加层。它使用 google.maps.OverlayView 作为其原型:
Label.prototype = new google.maps.OverlayView();
我不确定将该 js 文件的脚本标记放置在我的 index.html 文件中的何处。如果我将脚本标签放置在谷歌地图加载标签下方,如下所示:
....
<script async defer
src="https://maps.googleapis.com/maps/api/js?...
</script>
<script src="js/label.js"></script>
</body>
</html>
label.js 文件立即加载,而地图 api 尚未加载,导致错误。
我目前通过在地图加载回调中手动加载 JS 来解决这个问题:
function initMap() {
gMap = new google.maps.Map(document.getElementById(strMapDivName), {
center: {lat: 21, lng: 78},
mapTypeId: google.maps.MapTypeId.HYBRID,
zoom: 6,
heading: 90,
tilt: 0
});
// Load label.js afterwards so we can be sure that the google maps api has loaded
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", "js/label.js")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
这是解决这个问题的最好方法吗?
我知道为时已晚,但我使用下面的代码
var mapWaitCount = 0;
var mapWaitMax = 5;
function map_load(param1, param2, ...) { // if you need any param
mapWaitCount++;
// if api is loaded
if(typeof google != 'undefined') {
// your code here
}
// try again if until maximum allowed attempt
else if(mapWaitCount < mapWaitMax) {
console.log('Waiting attempt #' + mapWaitCount); // just log
setTimeout(function() { map_load(); }, 1000);
}
// if failed after maximum attempt, not mandatory
else if(mapWaitCount >= mapWaitMax) {
console.log('Failed to load google api');
}
}
map_load(param1, param2, ...) { // if you need any param
它使用超时来等待加载,尝试几次后就会停止
您应该在 API 调用中包含回调函数。
<script async
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&loading=async&callback=initMap">
</script>
然后您可以在回调函数中包含任何与地图相关的代码:
function initMap() {
// Your Google Maps related code here
}
如果您需要等到地图“就绪”,即地图显示有地图选项并且“空闲”,您可以使用:
google.maps.event.addListenerOnce(map, 'idle', function () {
// map is ready
});
但是您仍然应该将其包含在回调函数中。
Google 现在推荐各种其他方法来加载 API,但仍然支持直接脚本加载标记。
let map;
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 0, lng: 0 },
zoom: 4
});
}
window.initMap = initMap;
#map {
height: 180px;
}
<div id="map"></div>
<script async
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&loading=async&callback=initMap">
</script>
let map;
// initMap is now async
async function initMap() {
// Request libraries when needed, not in the script tag.
const { Map } = await google.maps.importLibrary("maps");
// Short namespaces can be used.
map = new Map(document.getElementById("map"), {
center: { lat: 0, lng: 0 },
zoom: 4
});
}
initMap();
#map {
height: 180px;
}
<div id="map"></div>
<script>
(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
key: "AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk",
v: "weekly",
// Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
// Add other bootstrap parameters as needed, using camel case.
});
</script>
当然,请将 API 密钥替换为您自己的。
更新一个老问题;在 React 中我使用了 NPM 模块:load-google-maps-api
在意识到这个存在并且可以节省一些时间之前,我开始自己创造这个树。
它将以 Promise 格式加载地图 API,因此您可以为加载后提供回调函数。
loadGoogleMapsApi().then(function (googleMaps) {
new googleMaps.Map(document.querySelector('.map'), {
center: {
lat: 40.7484405,
lng: -73.9944191
},
zoom: 12
})
}).catch(function (error) {
console.error(error)
})
您现在可以使用 Google Maps JavaScript API 加载器库
npm i @googlemaps/js-api-loader
const loader = new Loader({
apiKey: "",
version: "weekly"
});
loader
.load()
.then((google) => {
new google.maps.Map(document.getElementById("map"), mapOptions);
})
.catch(e => {
// do something
});
isMapApiLoaded?: boolean
loader
.load()
.then((google) => {
this.isMapApiLoaded = true
})
.catch(e => {
// do something
});
<google-map *ngIf="isMapApiLoaded">
<!-- ... -->
</google-map>
export class MapLoaderService {
onMapApiDidLoad$: BehaviorSubject<boolean> = new BehaviorSubject(null)
private _initLoader() {
this.mapLoader
.load()
.then((google) => {
this.onMapApiDidLoad$.next(true)
})
.catch((e) => {
this.onMapApiDidLoad$.next(false)
})
}
}
这是我制作并为我工作的泛型。
1)定义Google地图加载后要执行的函数
function ToExecuteAfterLoaded()
{
// Doing something here ///
console.log("Executing this function"); // per example //
}
2)等待功能
function WhenGoogleLoadedDo(fnt)
{
if(typeof google != 'undefined')
fnt();
else
setTimeout(function()
{(function(fnt)
{
WhenGoogleLoadedDo(fnt)
})(fnt)}, 500); // You can set timer as you wish //
}
3)在脚本中像这样调用ToExecuteAfterLoaded
WhenGoogleLoadedDo(ToExecuteAfterLoaded);
用 DOMContentLoaded 包装自定义标签怎么样?
document.addEventListener("DOMContentLoaded", function(event) {
Label.prototype = new google.maps.OverlayView();
});
参考: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded