如何等到 google 地图 API 加载完毕后再加载 google.maps.OverlayView 派生类

问题描述 投票:0回答:6

我有一个单独的 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)

}

这是解决这个问题的最好方法吗?

javascript google-maps google-maps-api-3
6个回答
7
投票

我知道为时已晚,但我使用下面的代码

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

它使用超时来等待加载,尝试几次后就会停止


7
投票

您应该在 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
});

但是您仍然应该将其包含在回调函数中。

编辑2024年

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>

或者,使用动态库导入 API:

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 密钥替换为您自己的。


1
投票

更新一个老问题;在 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)
})

1
投票

打字稿的做法

您现在可以使用 Google Maps JavaScript API 加载器库

  1. 奔跑
    npm i @googlemaps/js-api-loader
  2. 使用装载机
const loader = new Loader({
  apiKey: "",
  version: "weekly"
});

JavaScript方式

  1. 订阅装载机承诺
loader
  .load()
  .then((google) => {
    new google.maps.Map(document.getElementById("map"), mapOptions);
  })
  .catch(e => {
    // do something
  });

图书馆方式例如:角度

  1. 订阅装载机承诺
isMapApiLoaded?: boolean

loader
  .load()
  .then((google) => {
     this.isMapApiLoaded = true
  })
  .catch(e => {
    // do something
  });
  1. 仅在加载时显示地图
<google-map *ngIf="isMapApiLoaded"> 
  <!-- ... -->
</google-map>

附加(单例)

  1. 您可以在服务中使用加载程序,然后全局导入
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)
      })
  }
}

0
投票

这是我制作并为我工作的泛型。

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

0
投票

用 DOMContentLoaded 包装自定义标签怎么样?

      document.addEventListener("DOMContentLoaded", function(event) {
            Label.prototype = new google.maps.OverlayView();
      });

参考: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

© www.soinside.com 2019 - 2024. All rights reserved.