Javascript 如何在 Web 应用程序的单独文件中回调 Google Maps init

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38627259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:40:18  来源:igfitidea点击:

How to make a callback to Google Maps init in separate files of a web app

javascripthtmlangularjsgoogle-mapsgoogle-maps-api-3

提问by AlleyOOP

When I had my Google Maps API snippet:

当我拥有 Google Maps API 片段时:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

in index.html, I got the error: Uncaught InvalidValueError: initMap is not a function.

index.html,我收到错误:Uncaught InvalidValueError: initMap is not a function

I want to keep all of my bower_component, CSS, API, and script declarations in my index.htmlfile on my Yeoman-scaffolded AngularJS web app. The map I was actually trying to recreate would be on another route, let's call it route "afterlogin", just a basic map. I separated the js and the html html components into afterlogin.jsand afterlogin.html

我想在我的 Yeoman-scaffolded AngularJS Web 应用程序的文件中保留我的所有bower_component.CSS、API 和脚本声明index.html。我实际上试图重新创建的地图将在另一条路线上,我们称之为“登录后”路线,只是一张基本地图。我将 js 和 html html 组件分成afterlogin.jsafterlogin.html

There are a number of potential causes for this. One of which was presented here as a matter of adjusting the call to match the namespace, https://stackoverflow.com/a/34466824/1923016. Would this require an angular service? If so, how would the service work into the initMapfunction and its call in the Google maps api snippet?

造成这种情况的潜在原因有很多。其中之一是调整调用以匹配命名空间https://stackoverflow.com/a/34466824/1923016。这需要角度服务吗?如果是这样,该服务将如何initMap在 Google 地图 api 片段中使用该函数及其调用?

One of the complications is the order. I'm new to web app dev, but from what I can tell the index.htmlloads first, uses the url in the snippet to make the callback to the initMapfunction which is not featured in <script>...</script>in the index.htmlfile nor in the app.jsfile. Instead, since the init function is in a route's js code, it cannot be seen, hence the need for some kind of "namespace" version of the call. This leads to a console error even from the login route, which is not even where the divfor the map is.

并发症之一是订单。我是新来的Web应用开发,但我可以告诉的index.html第一负载,使用在片断的URL进行回调到initMap未在特色功能<script>...</script>index.html的文件,也没有在app.js文件中。相反,由于 init 函数位于路由的 js 代码中,因此无法看到它,因此需要某种“命名空间”版本的调用。这甚至会导致登录路由出现控制台错误,这甚至不是div地图所在的位置。

---- EDIT: ----

- - 编辑: - -

Also note that in this case, this did not do the trick:

还要注意,在这种情况下,这并没有起到作用:

window.initMap = function(){
//...
}

This also does not apply, as the function is never called: Uncaught InvalidValueError: initMap is not a function

这也不适用,因为该函数从未被调用:Uncaught InvalidValueError: initMap is not a function

-- -- -- -- -- --

-- -- -- -- -- --

afterlogin.js

登录后.js

angular.module('myappproject').controller('AfterloginCtrl', function ($scope) {

  function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 17,
      center: {lat: -33.8666, lng: 151.1958}
    });

    var marker = new google.maps.Marker({
      map: map,
      // Define the place with a location, and a query string.
      place: {
        location: {lat: -33.8666, lng: 151.1958},
        query: 'Google, Sydney, Australia'

      },
      // Attributions help users find your site again.
      attribution: {
        source: 'Google Maps JavaScript API',
        webUrl: 'https://developers.google.com/maps/'
      }
    });

    // Construct a new InfoWindow.
    var infoWindow = new google.maps.InfoWindow({
      content: 'Google Sydney'
    });

    // Opens the InfoWindow when marker is clicked.
    marker.addListener('click', function() {
      infoWindow.open(map, marker);
    });
  }
 });

afterlogin.html

登录后.html

<!DOCTYPE html>
<html>
    <head>
        <title>after login page</title>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
        <meta charset="utf-8">
        <style>
            html, body {
                height: 100%;
                margin: 0;
                padding: 0;
                }
            #map {
                height: 100%;
            }
        </style>
    </head>
    <body>

        <div id="map"></div>

    </body>
</html>

回答by Mosh Feu

Since the Google Maps SDK script load a synchronic (due the asyncattribute), there is the callbackparameter in the URL.

由于 Google Maps SDK 脚本加载同步(由于async属性),因此callbackURL 中有参数。

To solve the problem, you need to understand the asyncmechanism in google sdk

解决问题需要了解asyncgoogle sdk中的机制

The async attribute lets the browser render the rest of your website while the Maps JavaScript API loads. When the API is ready, it will call the function specified using the callback parameter.

async 属性允许浏览器在 Maps JavaScript API 加载时呈现网站的其余部分。当 API 准备就绪时,它将调用使用回调参数指定的函数。

https://developers.google.com/maps/documentation/javascript/tutorial#Loading_the_Maps_API

https://developers.google.com/maps/documentation/javascript/tutorial#Loading_the_Maps_API

So the solution is to load the script synchronic:

所以解决方案是同步加载脚本:

In the script tag that loads the Maps JavaScript API, it is possible to omit the async attribute and the callback parameter. This will cause the loading of the API to block until the API is downloaded.

This will probably slow your page load. But it means you can write subsequent script tags assuming that the API is already loaded.

在加载 Maps JavaScript API 的脚本标记中,可以省略 async 属性和回调参数。这将导致 API 的加载阻塞,直到 API 被下载。

这可能会减慢您的页面加载速度。但这意味着您可以在假设 API 已经加载的情况下编写后续脚本标签。

https://developers.google.com/maps/documentation/javascript/tutorial#sync

https://developers.google.com/maps/documentation/javascript/tutorial#sync

  1. You can remove the asyncattribute that way, the page will stop running until the script will complete downloaded and run on the page. So, when the browser will get to your code, all the SDK object will be available.
  2. Now, since there is not code that calls to the initMapfunction (remember: who called it, it was the sdk script which call it only in the asyncmode), you need to call it by yourself. So, just call it in the end of the controller.
  1. 您可以通过async这种方式删除该属性,页面将停止运行,直到脚本完成下载并在页面上运行。因此,当浏览器访问您的代码时,所有 SDK 对象都将可用。
  2. 现在,由于没有调用initMap函数的代码(记住:是谁调用的,是sdk脚本只在async模式下调用它),你需要自己调用它。所以,只需在控制器的末尾调用它。

回答by morgler

I could fix it in my code by using the callback and declaring the initMapsfunction on windowas you did:

我可以通过使用回调并像您一样声明initMaps函数来在我的代码中修复它window

window.initMap = function(){
  //...
}

However, the trick was to load my custom JS (which also includes the above declaration of initMaps) beforeloading Google Maps:

然而,诀窍是加载谷歌地图之前加载我的自定义 JS(其中还包括上面的声明initMaps):

<script async src="myCustomJsInclduingInitMapsFunction.js"></script>
<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script>

Hope this helps.

希望这可以帮助。