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

Posted

技术标签:

【中文标题】如何在 Web 应用程序的单独文件中回调 Google Maps init【英文标题】:How to make a callback to Google Maps init in separate files of a web app 【发布时间】:2016-12-02 07:23:49 【问题描述】:

当我拥有 Google Maps API sn-p 时:

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

index.html,我得到了错误:

未捕获的 InvalidValueError:initMap 不是函数

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

造成这种情况的潜在原因有很多。此处介绍了其中之一,即调整调用以匹配命名空间 https://***.com/a/34466824/1923016 。这需要角度服务吗?如果是这样,该服务将如何工作到 initMap 函数及其在 Google 地图 api sn-p 中的调用?

其中一个复杂的问题是顺序。我是 web 应用程序开发的新手,但据我所知,index.html 首先加载,使用 sn-p 中的 url 来回调 initMap 函数,该函数在 &lt;script&gt;...&lt;/script&gt; 中没有index.html 文件或 app.js 文件中。相反,由于 init 函数在路由的 js 代码中,因此无法看到,因此需要某种“命名空间”版本的调用。这会导致控制台错误,即使是登录路径,也不是地图的 div 所在的位置。

---- 编辑:----

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

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

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

-- -- -- -- --

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

登录后.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>

【问题讨论】:

A.尝试删除属性async 然后你不需要回调。 B.可以使用Angular Google Maps等模块 @MoshFeu 没有更多错误,但没有显示地图 当然不是。尝试调用controller末尾的initMap 好极了。请解释 我在答案中解释了它,以便对其他人有所帮助.. 【参考方案1】:

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

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

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

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

所以解决办法是同步加载脚本:

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

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

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

    您可以删除async 属性,这样页面将停止运行,直到脚本完成下载并在页面上运行。因此,当浏览器访问您的代码时,所有 SDK 对象都将可用。 现在,由于没有调用initMap函数的代码(记住:是谁调用的,是sdk脚本只在async模式下调用它),你需要自己调用它。因此,只需在控制器末尾调用它即可。

【讨论】:

这是一个解决方案。然而我觉得这并不令人满意,因为同步加载地图会大大减慢页面加载速度。在异步情况下真的没有办法使用谷歌地图回调吗? 您可以在body 的末尾添加此脚本,它不会中断渲染(但会延迟window.load 事件)。当您使用async 时,您必须确保脚本已下载并执行,然后才能创建地图。如果需要,可以通过 (this) 检测脚本状态【参考方案2】:

我可以在我的代码中修复它,方法是使用回调并像你一样在 window 上声明 initMaps 函数:

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

但是,诀窍是在加载 Google 地图之前加载我的自定义 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>

希望这会有所帮助。

【讨论】:

我希望这会起作用,但是s a reciprocal error in that logic, that is, Uncaught ReferenceError: google is not defined`来自我调用var map = new google.maps.Map(...)的initMap函数。因此,除非我可以在自定义脚本中加载 Google 地图脚本,否则据我所知这是行不通的。 似乎不起作用,地图代码抱怨initMap is not a function 实际上,它确实有效。但在 Typescript 中,我必须使用 window['initMaps'] = function() ... 。简单地使用window.initMaps = ... 是行不通的。

以上是关于如何在 Web 应用程序的单独文件中回调 Google Maps init的主要内容,如果未能解决你的问题,请参考以下文章

如何让asp.net应用程序定时自动执行代码

如何使用 msbuild 从 dotnetcore web-api 项目中触发“ng build”,但将 angular 项目保存在单独的文件夹中?

如何让用户从 web 应用程序上的 firebase 存储下载图像?

如何在回调时在 Kivy 布局之间切换?

为啥必须在 spring-boot 中为 web 应用程序提供单独的 @Controller 类文件?

如何在IIS / Azure中单独部署webconfig更改?