前言
很多年前写过一篇 Google Map 谷歌地图, 这篇算是翻新版本.
Google Map Registration
Google Maps Platform 是整个 Google Map 的大本营. 里面有许许多多的 Services. Embed 和 JavaScript API 只是其中的两个.
首先, Services 不是免费的. 只是 Google 每个月有 free USD 200 块让你花. 可以算是间接免费.
但是申请账户需要绑定银行卡哦 (以前是不需要的, 如果只是用 Maps Embed API 则不需要绑定卡)
下图是它的 Documentation
这篇的内容, 大部分都是来自 JS API 和 Embed API 文档.
申请的部分我就不 step by step 讲了. 大概有几个东西需要弄:
-
申请 Google Cloud (Map 属于 Cloud 的一部分)
-
绑卡
-
Create New Project
-
Enable Services (Maps Embed / JavaScript API)
-
做 API Key (API Key 要设定只有在指定的 Domain 内能用哦 (这个叫 Key restrictions), 因为 API Key 是放在 HTML 公开的, 任何人都可以直接拿到.
Google Maps Embed API
Embed Map 就是把 Map 嵌套进网站里. 效果:
它是通过 iframe 完成的. 左上角是一个 location info. 中间有一个 drop point 就是目标地点 (通常就是公司的地址)
要制作 iframe 不需要什么 coding. 用 Generating an iframe 就可以了.
输入查询, 比如公司名字 > 点击 Looks good!
然后输入 API Key
API 在 Cloud 里面
接着 copy iframe 的 code, 放到要 display 的页面区域就可以了.
Options
想配置 config 可以通过 parameters. 参考: Embedding a map
上面我们使用了 iframe generator, 但其实它就是替我们生成 parameters 而已.
下面这个是手写的 iframe src
https://www.google.com/maps/embed/v1/place?q=place_id:ChIJcXt2BFgZ2jERY1RQlGLGTzU&zoom=10&key=your-key
通常可能需要配置的变量是: version, place_id (或者直接用 q, q stand for query), zoom, key, language. 参考: place mode
局限
Embed API 虽然简单, 但是也有不少局限性.
-
不支持 multiple location. 它只可以放一个地点. 如果公司有许多分行. 那就不够用了.
-
marker (中间的 drop point 术语叫 marker) 没有任何点击事件. location info 在右上角并不显眼. 用户可能会点击 marker, 但却没有任何反应.
而这两个局限可以通过 Maps JavaScript API 来解决.
Google Maps JavaScript API
最终效果
一开始有 3 个 location, 点击 location 会出现 location info.
Simple Map
最终效果有几个难点, 我们先从最简单的开始.
setup HTML
首先是 HTML 引入 Script 和一个 div 作为 map 的渲染位置
bundle.js 是我们的 main.ts
<script src="./bundle.js" defer>script> <script src="https://maps.googleapis.com/maps/api/js?key=your-key&libraries=places&callback=initMap" defer >script>
这个 Script 可以直接放在 HTML 或者用 JavaScript 动态 append 出去都可以. 确保执行的顺序就可以了.
有 3 个 parameters 需要注意
-
key 和 Embed API 是相同的 key
-
libraries, 由于会使用到 PlacesService 所以这里需要 “import” 它.
-
callback, 当 Script 加载好后会调用 initMap 这个全局函数. 所以在 main.ts 我们 assign callback 方法到 window.initMap 里.
setup JavaScript
先安装 types
yarn add @types/google.maps --dev
然后定义 callback
declare global {
interface Window {
initMap: () => void;
}
}
window.initMap = () => {
new google.maps.Map(document.querySelector(".map")!, {
center: {
lat: 1.284491,
lng: 103.845951,
},
zoom: 10,
});
};
效果
这个就是最简单的 map 了.
center 和 zoom 是一定要 set 的, 不然什么都看不见哦.
Scolling Problem
默认情况下, 在 map 上 scrolling 的效果是 zoom. 这个体验不一定是期望的, 用户可能是想 scroll 页面, 只是鼠标碰巧放在 map 上面.
解决方法是在 config 添加 gestureHandling
new google.maps.Map(document.querySelector(".map")!, {
gestureHandling: "cooperative",
});
效果
当用户不小心 scroll 到的, 不会有 zoom 的效果, 同时会出现提示. 用 zoom 请使用 ctrl + scroll.
Custom Map Style
上面最终效果的主题颜色并不是默认的. 它是灰色系的.
主题可以到这里 mapstyle.withgoogle.com, 它有 2 种方法.
-
用 Cloud, 这样代码就不需要包含 styling 逻辑. 它在一开始的 Script API 就会链接到 Cloud 设置好的 Styling.
-
下载 JSON 文件.
下面就是最终效果的配置
它默认的 labels.icon 会把 Singapore 给 hide 起来, 所以我修改了它的 JSON file.
最后把 style 掉进去就可以了.
new google.maps.Map(document.querySelector(".map")!, {
styles: [], //
});
Places Library
它是一个 service, 可以通过 query 找到 place info. 比如 query=my-company-name
它会返回坐标, 地址, reviews count, reviews rating, opening hours 等等.
它有许多方法可以用来 search, 但目前只用到 Find Place from Query 就足够了.
代码
const map = new google.maps.Map(document.querySelector(".map")!);
const service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery(
{
query: "Coolman Aircon",
fields: [
"place_id",
"geometry",
"name",
"formatted_address",
"rating",
"user_ratings_total",
],
},
(results, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
console.log("callback", results!.filter(result => result.name! === query)[0]);
}
}
);
还有什么可用的 fields 可以参考这里
注: query=my-company-name 是有可能会找到超过 1 个 results 的哦, 我会通过 filter name 来获取准确的那一个.
效果
分别对应了 info window 需要的内容
name, formatted_address, rating, user_ratings_total
view larger map 需要 place_id
directions 则是 name + formatted_address
geometry 是给 marker 用的
Marker
const map = new google.maps.Map(document.querySelector(".map")!, {
center: {
lat: 1.284491,
lng: 103.845951,
},
zoom: 10,
});
new google.maps.Marker({
map,
position: {
lat: 1.284491,
lng: 103.845951,
},
});
position 就拿上面 place info 的 geometry.
Marker Styling
参考:
默认的 marker 是红色的. 通常和网站主题颜色不搭.
有 2 种替换方式.
- 用 svg path. 这个挺难搞的, 它长这样.
首先那个 path 可以从 .svg file 里面抄出来. 如果有多个 path 就用逗号分割, 然后拼接到后面就可以了.
fillColor 控制颜色, fillOpacity 默认是 0 哦. 如果要颜色记得配置
stroke 是控制 border
最难搞的是 icon 的 size. 它只能通过 scale 去控制大小. 然后 origin 老是抓不准. 所以会一直跑位. 估计是修改配置 anchor 或者 origin 之类的.
但我已经没有耐性玩了. 所以还是用第 2 种方法吧.
- 用 .svg 图片
提前把 svg 图片弄好. fill, width, heigth 都 set 好. 然后直接 link 就可以了.
不嫌弃的话, 也可以用 Google 提供的 icon: Google Earth/Maps Icons
Zoom to All Marker
上面 create map 的时候, 我们 hardcode 了 center 和 zoom. 这样是不 ok 的.
正确的做法是依据所有的 marker 调整 zoom, 尽可能的显示所有 markers.
参考: Stack Overflow – Auto-center map with multiple markers in Google Maps API v3
const map = new google.maps.Map(document.querySelector(".map")!, {
maxZoom: 10, // 避免 auto zoom 太大
});
const bounds = new google.maps.LatLngBounds();
bounds.extend({
// 收集 marker 坐标 1
lat: 1.284491,
lng: 103.845951,
});
bounds.extend({
// 收集 marker 坐标 2
lat: 1.284491,
lng: 103.845951,
});
map.fitBounds(bounds); // 调整 map zoom 和 center
主要用到了 LatLngBounds 和 fitBounds 方法. 担心自动 zoom 太大的话, 可以 set 一个 maxZoom.
Info Window
const map = new google.maps.Map(document.querySelector(".map")!, {
center: {
lat: 1.284491,
lng: 103.845951,
},
zoom: 10,
});
const marker = new google.maps.Marker({
position: {
lat: 1.284491,
lng: 103.845951,
},
map,
clickable: true,
});
const infowindow = new google.maps.InfoWindow({
content: Hello World
,
});
marker.addListener("click", () => {
infowindow.open({
anchor: marker,
map,
shouldFocus: false,
});
});
assign Raw HTML 给 InfoWindow.content 就可以了. CSS Selector 可以直接 select 到 .map .my-h1
所以 apply style 不是问题. (以前好像是不可以的, 在 Stack Overflow 有看到以前的许多提问)
Google Map Link
最后说一下 reviews, view larger map, directions 的 link
参考:
Stack Overflow – Link to Google Maps Directions using place_id
Stack Overflow – Getting Google Maps link from place_id
reviews link
const reviewsLink = https://search.google.com/local/reviews?placeid=${data.placeId}
placeId 到 place info 里拿.
view larger map link
const viewLargerMapLink = https://maps.google.com/maps?q=place_id:${data.placeId}
directions link
const directionsLink = https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent(
${data.name},${data.address}
)}
direction 没有用到 placeId, 反而是用到了 name 和 formatted_address
Original: https://www.cnblogs.com/keatkeat/p/16467565.html
Author: 兴杰
Title: Google Maps Embed API & JavaScript API
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/535730/
转载文章受原作者版权保护。转载请注明原作者出处!