如何在 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.js
和afterlogin.html
造成这种情况的潜在原因有很多。此处介绍了其中之一,即调整调用以匹配命名空间 https://***.com/a/34466824/1923016 。这需要角度服务吗?如果是这样,该服务将如何工作到 initMap
函数及其在 Google 地图 api sn-p 中的调用?
其中一个复杂的问题是顺序。我是 web 应用程序开发的新手,但据我所知,index.html
首先加载,使用 sn-p 中的 url 来回调 initMap
函数,该函数在 <script>...</script>
中没有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的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 msbuild 从 dotnetcore web-api 项目中触发“ng build”,但将 angular 项目保存在单独的文件夹中?
如何让用户从 web 应用程序上的 firebase 存储下载图像?