向网站添加地图 (JavaScript)

1. 准备工作

在此 Codelab 中,您将学习在 Web 平台上开始使用 Google Maps Platform 需知的内容。您将学习所有基础知识,从准备工作到加载 Maps JavaScript API、显示您的第一个地图、使用标记和标记聚类、在地图上绘图,以及处理用户互动等,面面俱到。

构建内容

e52623cb8578d625.png

在此 Codelab 中,您将构建 Web 应用,用于执行以下操作:

  • 加载 Maps JavaScript API
  • 显示以澳大利亚悉尼为中心的地图
  • 显示悉尼热门景点的自定义标记
  • 实施标记聚类
  • 启用用户互动功能,这样,当用户点击标记时,能够重新设置中心并在地图上绘制圆形区域

学习内容

  • Google Maps Platform 使用入门
  • 通过 JavaScript 代码动态加载 Maps JavaScript API
  • 加载地图
  • 使用标记、自定义标记和标记聚类
  • 使用 Maps JavaScript API 事件系统提供用户互动功能
  • 动态控制地图
  • 在地图上绘图

2. 前提条件

您必须熟悉以下各项内容,才能完成此 Codelab。如果您已经能够熟练使用 Google Maps Platform,请直接跳到该 Codelab!

所需的 Google Maps Platform 产品

在此 Codelab 中,您将使用以下 Google Maps Platform 产品:

完成此 Codelab 的其他要求

要完成此 Codelab,您需要以下帐号、服务和工具:

  • 已启用结算功能的 Google Cloud Platform 帐号
  • 已启用 Maps JavaScript API 的 Google Maps Platform API 密钥
  • 具备 JavaScript、HTML 和 CSS 方面的基础知识
  • 计算机上已安装 Node.js
  • 您自己喜欢用的文本编辑器或 IDE

Google Maps Platform 使用入门

如果您之前从未使用过 Google Maps Platform,请参阅 Google Maps Platform 使用入门指南或观看 Google Maps Platform 使用入门播放列表中的视频,完成以下步骤:

  1. 创建一个结算帐号。
  2. 创建一个项目。
  3. 启用所需的 Google Maps Platform API 和 SDK(已在上一节中列出)。
  4. 生成一个 API 密钥。

3. 进行设置

设置 Google Maps Platform

如果您还没有已启用结算功能的 Google Cloud Platform 帐号和项目,请参阅 Google Maps Platform 使用入门指南,创建结算帐号和项目。

  1. Cloud Console 中,点击项目下拉菜单,选择要用于此 Codelab 的项目。

  1. Google Cloud Marketplace 中启用此 Codelab 所需的 Google Maps Platform API 和 SDK。为此,请按照此视频此文档中的步骤操作。
  2. 在 Cloud Console 的凭据页面中生成 API 密钥。您可以按照此视频此文档中的步骤操作。必须要有 API 密钥才能向 Google Maps Platform 发送请求。

Node.js 设置

如果您还没有 Node.js,请转到 https://nodejs.org/,然后在计算机上下载并安装 Node.js 运行时。

Node.js 附带 npm 软件包管理器,您可以借此安装此 Codelab 的依赖项。

项目入门模板设置

在开始此 Codelab 之前,请按照下列步骤下载入门项目模板以及完整的解决方案代码:

  1. 请访问 https://github.com/googlecodelabs/maps-platform-101-js,下载此 Codelab 的 GitHub 代码库或创建分支。

入门项目位于 /starter 目录,其中包含完成此 Codelab 所需的基本文件结构。您需要的所有内容均位于 /starter/src 目录中。2. 下载入门项目后,请运行 /starter 目录中的 npm install。此操作会安装 package.json 中列出的所有必需依赖项。3. 安装依赖项后,请运行目录中的 npm start

入门项目已设置完毕,您可以使用 webpack-dev-server 编译并运行您在本地编写的代码。webpack-dev-server 还会在您更改代码时自动在浏览器中重新加载您的应用。

如果您希望运行完整的解决方案代码,请在 /solution 目录中完成上述设置步骤。

4. 加载 Maps JavaScript API

开始之前,请确保按照准备工作中的步骤操作。已全部完成?好了,现在可以使用 Google Maps Platform 构建您的第一个 Web 应用了!

Maps JavaScript API 是使用网页版 Google Maps Platform 的基础。此 API 提供 JavaScript 接口,方便您使用 Google Maps Platform 的所有功能,包括地图、标记、绘图工具以及其他 Google Maps Platform 服务(例如地点)。

如果您之前使用过 Maps JavaScript API,则可能熟悉加载方式,即在 HTML 文件中插入 script 标记,如下所示:

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

这仍然是非常有效的 API 加载方式,但现代 JavaScript 通常会动态添加代码中的依赖项。若要通过代码实现与上述 script 标记同等的效果,您需要使用 @googlemaps/js-api-loader 模块。项目的 package.json 文件的依赖项中已包含 JS API 加载器,因此,当您在前面运行 npm install 时就已安装了该加载器。

若要使用 JS API 加载器,请执行以下操作:

  1. 打开 /src/app.js。您将在此文件中完成此 Codelab 的所有操作。
  2. 从 @googlemaps/js-api-loader 中导入 Loader 类。

    app.js 的顶部添加以下内容:
     import { Loader } from '@googlemaps/js-api-loader';
    
  3. 创建一个 apiOptions 对象。

    Loader 类需要一个 JSON 对象,用于指定可加载 Maps JavaScript API 的各种选项,包括 Google Maps Platform API 密钥、要加载的 API 版本以及由您要加载的 Maps JS API 提供的其他任何库。在本 Codelab 中,您只需将以下内容附加到 app.js,即可指定 API 密钥:
     const apiOptions = {
       apiKey: "YOUR API KEY"
     }
    
  4. 创建 Loader 实例并向其传递 apiOptions
     const loader = new Loader(apiOptions);
    
  5. 加载 Maps JS API。

    若要加载 API,请调用 Loader 实例上的 load()。JS API 加载器会返回一个在 API 加载完毕可供使用后解析的 promise。添加以下桩来加载 API 并处理 promise:
     loader.load().then(() => {
       console.log('Maps JS API loaded');
     });
    

如果一切顺利,您应该会在浏览器控制台中看到 console.log 语句:

4fa88d1618cc7fd.png

回顾一下,您现在通过代码动态加载了 Maps JavaScript API,并定义了 Maps JavaScript API 加载完成后要执行的回调函数。

您的 app.js 文件应如下所示:

    import { Loader } from '@googlemaps/js-api-loader';

    const apiOptions = {
      apiKey: "YOUR API KEY"
    }

    const loader = new Loader(apiOptions);

    loader.then(() => {
      console.log('Maps JS API Loaded');
    });

Maps JavaScript API 现已加载,接下来您将加载地图。

5. 显示地图

是时候显示您的第一个地图了!

Maps JavaScript API 中最常用的部分是 google.maps.Map,这是我们用于创建和操作地图实例的类。不妨创建一个名为 displayMap() 的新函数,看看具体操作方式。

  1. 确定您的地图设置。

    Maps JavaScript API 支持各种不同的地图设置,但只有以下两项设置是必需的:
    • center:设置地图中心的纬度和经度。
    • zoom:设置地图的初始缩放级别。
    使用以下代码将地图中心设为澳大利亚悉尼,将缩放级别设为 14(正好是显示城市中心的正确缩放级别)。
     function displayMap() {
       const mapOptions = {
         center: { lat: -33.860664, lng: 151.208138 },
         zoom: 14
       };
     }
    
  2. 获取 div,也就是将地图注入 DOM 的位置。

    在显示地图之前,您需要告知 Maps JavaScript API 希望在页面的什么位置显示地图。如果快速浏览 index.html,您会发现其中存在如下所示的 div
     <div id="map"></div>
    
    若要告知 Maps JavaScript API 这是您希望的地图注入位置,请使用 document.getElementById 获取它的 DOM 引用:
     const mapDiv = document.getElementById('map');
    
  3. 创建 google.maps.Map 实例。

    若要请求 Maps JavaScript API 创建可显示的新地图,请创新 google.maps.Map 实例,然后将其传入 mapDivmapOptions。您还可以通过此函数返回 Map 实例,以便稍后借此执行更多操作:
     const map = new google.maps.Map(mapDiv, mapOptions);
     return map;
    
  4. 地图可以显示了!

    确定创建地图实例的所有逻辑之后,只需从 JS API promise 处理程序中调用 displayMap(),以便在 Maps JavaScript API 加载后调用该函数:
     loader.then(() => {
       console.log('Maps JS API loaded');
       const map = displayMap();
     });
    

现在,您应该可以在浏览器中看到一个精美的悉尼地图了!

fb0cd6bc38532780.png

回顾一下,您在此步骤中定义了地图的显示选项、创建了新的地图实例并将其注入了 DOM。

您的 displayMap() 函数应如下所示:

function displayMap() {
  const mapOptions = {
    center: { lat: -33.860664, lng: 151.208138 },
    zoom: 14
  };
  const mapDiv = document.getElementById('map');
  const map = new google.maps.Map(mapDiv, mapOptions);
  return map;
}

6. 云端地图样式设置(可选)

您可以使用云端地图样式设置自定义地图样式。

创建地图 ID

如果您尚未使用关联的地图样式创建地图 ID,请参阅地图 ID 指南完成以下步骤:

  1. 创建地图 ID。
  2. 将地图 ID 与地图样式相关联。

为您的应用添加地图 ID

若要使用您创建的地图 ID,请修改 app.js 文件中的 displayMap 函数,然后将地图 ID 传入 mapOptions 对象的 mapId 属性。

app.js

function displayMap() {
  const mapOptions = {
    center: { lat: -33.860664, lng: 151.208138 },
    zoom: 14,
    mapId: 'YOUR_MAP_ID'
  };
  const mapDiv = document.getElementById('map');
  return new google.maps.Map(mapDiv, mapOptions);
}

完成此步骤后,您应该会在地图上看到所选的样式!

7. 向地图添加标记

虽然开发者可以借助 Maps JavaScript API 执行很多操作,但是在地图上添加标记绝对是最受欢迎的操作。借助标记,您可以在地图上显示特定点,并且标记是最常用的处理用户互动的界面元素。如果之前使用过 Google 地图,那么您可能熟悉默认标记,如下所示:

590815267846f166.png

在此步骤中,您将使用 google.maps.Marker 在地图上添加标记。

  1. 为您的标记位置定义对象。

    为此,请创建新的 addMarkers() 函数,并声明 locations 对象,该对象包含悉尼热门旅游景点一系列用纬度/经度表示的点。

    另请注意,您需要将 Map 实例传递给此函数。稍后,您在创建标记实例时需要使用此函数。
     function addMarkers(map) {
       const locations = {
         operaHouse: { lat: -33.8567844, lng: 151.213108 },
         tarongaZoo: { lat: -33.8472767, lng: 151.2188164 },
         manlyBeach: { lat: -33.8209738, lng: 151.2563253 },
         hyderPark: { lat: -33.8690081, lng: 151.2052393 },
         theRocks: { lat: -33.8587568, lng: 151.2058246 },
         circularQuay: { lat: -33.858761, lng: 151.2055688 },
         harbourBridge: { lat: -33.852228, lng: 151.2038374 },
         kingsCross: { lat: -33.8737375, lng: 151.222569 },
         botanicGardens: { lat: -33.864167, lng: 151.216387 },
         museumOfSydney: { lat: -33.8636005, lng: 151.2092542 },
         maritimeMuseum: { lat: -33.869395, lng: 151.198648 },
         kingStreetWharf: { lat: -33.8665445, lng: 151.1989808 },
         aquarium: { lat: -33.869627, lng: 151.202146 },
         darlingHarbour: { lat: -33.87488, lng: 151.1987113 },
         barangaroo: { lat: - 33.8605523, lng: 151.1972205 }
       }
     }
    
  2. 为您希望显示的每个标记创建 google.maps.Marker 实例。

    若要创建标记,请使用下面的代码,通过 locations 对象使用 for...in 循环进行迭代,为每个标记的渲染方式创建一系列选项,然后为每个位置创建 google.maps.Marker 实例。

    请注意 markerOptionsicon 属性。还记得之前的默认地图图钉吗?您知道,您可以将图钉自定义为自己想要的任意图片吗?您可以执行这项操作!

    借助 icon 属性,您可以提供要用作自定义标记的所有图片文件的路径。如果您在此 Codelab 一开始就使用了我们的项目模板,那么 /src/images 中已包含图片。

    另请注意,您需要以数组形式存储标记实例,并通过函数返回实例,以便稍后使用。
     const markers = [];
     for (const location in locations) {
       const markerOptions = {
         map: map,
         position: locations[location],
         icon: './img/custom_pin.png'
       }
       const marker = new google.maps.Marker(markerOptions);
       markers.push(marker);
     }
     return markers;
    
  3. 显示标记。

    每次创建新 google.maps.Marker 实例时,Maps JavaScript API 都会自动创建并显示标记,因此您现在只需更新 JS API promise 处理程序,即可调用 addMarkers() 并向其传递 Map 实例:
     loader.then(() => {
       console.log('Maps JS API loaded');
       const map = displayMap();
       const markers = addMarkers(map);
     });
    

现在,您应该可以在地图上看到自定义标记了:

1e4a55de15215480.png

回顾一下,在此步骤中,您定义了一组标记位置,并且为每个位置创建了支持自定义标记图标的 google.maps.Marker 实例。

您的 addMarkers() 函数应如下所示:

    function addMarkers(map) {
      const locations = {
        operaHouse: { lat: -33.8567844, lng: 151.213108 },
        tarongaZoo: { lat: -33.8472767, lng: 151.2188164 },
        manlyBeach: { lat: -33.8209738, lng: 151.2563253 },
        hyderPark: { lat: -33.8690081, lng: 151.2052393 },
        theRocks: { lat: -33.8587568, lng: 151.2058246 },
        circularQuay: { lat: -33.858761, lng: 151.2055688 },
        harbourBridge: { lat: -33.852228, lng: 151.2038374 },
        kingsCross: { lat: -33.8737375, lng: 151.222569 },
        botanicGardens: { lat: -33.864167, lng: 151.216387 },
        museumOfSydney: { lat: -33.8636005, lng: 151.2092542 },
        maritimeMuseum: { lat: -33.869395, lng: 151.198648 },
        kingStreetWharf: { lat: -33.8665445, lng: 151.1989808 },
        aquarium: { lat: -33.869627, lng: 151.202146 },
        darlingHarbour: { lat: -33.87488, lng: 151.1987113 },
        barangaroo: { lat: - 33.8605523, lng: 151.1972205 }
      }
      const markers = [];
      for (const location in locations) {
        const markerOptions = {
          map: map,
          position: locations[location],
          icon: './img/custom_pin.png'
        }
        const marker = new google.maps.Marker(markerOptions);
        markers.push(marker);
      }
      return markers;
    }

在下一步中,您将了解如何使用标记聚类改善标记的用户体验。

8. 启用标记聚类

使用多个标记或标记彼此靠得很近时,您可能会遇到如下问题:标记重叠或看起来过于拥挤,导致用户体验不佳。例如,在上一步创建标记后,您可能已注意到此问题:

6e39736160c6bce4.png

这正是标记聚类的用武之地。标记聚类是另一种经常实施的地图项,它将临近的标记组合为单一图标,并且该图标能够随缩放级别而改变,如下所示:

4f372caab95d7499.png

标记聚类算法会将地图的可见区域划分为网格,然后聚集位于同一单元格的图标。幸运的是,您不必为任何操作担心,因为 Google Maps Platform 团队创建了一个实用的开源实用程序库 MarkerClustererPlus,可以自动为您执行各项操作。您可以查看 MarkerClustererPluson GitHub 的源代码。

  1. 导入 MarkerCluster

    对于此 Codelab 的模板项目,package.json 文件中声明的依赖项已包含 MarkerClustererPlus 实用程序库,因此,当您在此 Codelab 开头运行 npm install 时就已安装了该库。

    若要导入该库,请在 app.js 文件的顶部添加以下代码:
     import MarkerClusterer from '@google/markerclustererplus';
    
  2. 创建新 MarkerClusterer 实例。

    若要创建标记聚类,您需要执行以下两项操作:提供用于标记聚类的图标;创建新 MarkerClusterer 实例。

    首先,声明一个对象,指定要使用的图标的路径。在模板项目中,./img/m 中已保存了一系列图片。请注意,图片文件名按同类前缀依序编号:m1.pngm2.pngm3.png,以此类推。

    在标记聚类器的选项中设置 imagePath 属性时,您只需提供路径和文件前缀,标记聚类器会自动使用该前缀的所有文件,并在末尾附加数字。

    其次,创建一个新 MarkerClusterer 实例,并向其传递 Map 实例(您希望在此处显示标记聚类)以及您希望聚集的一组 Marker 实例。
     function clusterMarkers(map, markers) {
       const clustererOptions = { imagePath: './img/m' }
       const markerCluster = new MarkerClusterer(map, markers, clustererOptions);
     }
    
  3. 显示标记聚类。

    从 JS API promise 处理程序中调用 clusterMarkers()。在函数调用中创建 MarkerClusterer 实例时,系统会自动将标记聚类添加到地图。
     loader.then(() => {
       console.log('Maps JS API loaded');
       const map = displayMap();
       const markers = addMarkers(map);
       clusterMarkers(map, markers);
     });
    

现在,您应该会在地图上看到几个标记聚类。

e52623cb8578d625.png

请注意,如果您执行放大或缩小操作,MarkerClustererPlus 会自动为您重新调整聚类的编号和大小。您还可以点击放大任意标记聚类图标,查看相应聚类包含的所有标记。

d572fa11aca13eeb.png

回顾一下,在此步骤中,您导入了开源 MarkerClustererPlus 实用程序库,并用它创建了 MarkerClusterer 实例,自动将您在上一步中创建的标记加入聚类。

您的 clusterMarkers() 函数应如下所示:

    function clusterMarkers(map, markers) {
      const clustererOptions = { imagePath: './img/m' }
      const markerCluster = new MarkerClusterer(map, markers, clustererOptions);
    }

接下来,您将学习如何处理用户互动。

9. 添加用户互动

您现在有一个精美地图,显示了悉尼最热门的一些旅游目的地。在此步骤中,您将利用 Maps JavaScript API 的事件系统对用户互动进行一些额外处理,以便进一步改善地图的用户体验。

Maps JavaScript API 提供全面的事件系统,该系统允许您使用 JavaScript 事件处理脚本通过代码处理各种用户互动。例如,您可以创建事件监听器以触发互动(例如,用户点击地图和标记、平移地图的视图、放大和缩小等)的代码执行。

在这一步中,您将为标记添加点击监听器,然后以编程方式实现地图平移,将用户点击的标记置于地图中心。

  1. 在标记上设置点击监听器。

    Maps JavaScript API 中支持事件系统的所有对象均实施一组标准函数,用于处理用户互动(例如 addListenerremoveListener 等)。

    若要为每个标记添加点击事件监听器,请迭代 markers 数组并调用标记实例上的 addListener,为 click 事件附加监听器:
     function addPanToMarker(map, markers) {
       markers.map(marker => {
         marker.addListener('click', event => {
    
         });
       });
     }
    
  2. 平移到所点击的标记。

    每当用户点击或点按标记时,系统就会触发 click 事件,并且以 JSON 对象的形式返回事件,提供所点击界面元素的相关信息。为了改善地图的用户体验,您可以处理 click 事件并使用其 LatLng 对象来获取所点击标记的纬度和经度。

    获取相关值之后,只需将其传递给 Map 实例的内置 panTo() 函数,即可在事件处理脚本的回调函数中添加以下代码,从而顺畅平移地图,将地图中心重新设置为点击的标记所在位置:
     const location = { lat: event.latLng.lat(), lng: event.latLng.lng() };
     map.panTo(location);
    
  3. 分配点击监听器。

    从 JS API promise 处理程序中调用 addPanToMarker(),并向其传递地图和标记,以执行代码并分配点击监听器。
     loader.then(() => {
       console.log('Maps JS API loaded');
       const map = displayMap();
       const markers = addMarkers(map);
       clusterMarkers(map, markers);
       addPanToMarker(map, markers);
     });
    

现在,请转到浏览器,然后点击您的标记。当用户点击标记时,您应当会看到地图自动平移以重新设置中心。

回顾一下,在此步骤中,您使用了 Maps JavaScript API 的事件系统,为地图上的所有标记分配点击监听器,从已触发的点击事件中检索标记的经度和纬度,并且借此在用户点击标记时重新设置地图中心。

您的 addPanToMarker() 函数应如下所示:

    function addPanToMarker(map, markers) {
      markers = markers.map(marker => {
        marker.addListener('click', event => {
          const location = { lat: event.latLng.lat(), lng: event.latLng.lng() };
          map.panTo(location);
        });
      });
      return markers;
    }

就差一步了!接下来,您可以利用 Maps JavaScript API 的绘图功能,进一步改善地图的用户体验。

10. 在地图上绘制

到目前为止,您已创建了悉尼地图,显示了热门旅游目的地的标记并处理了用户互动。在此 Codelab 的最后一步中,您将使用 Maps JavaScript API 的绘图功能,为您的地图体验添加其他实用地图项。

想象一下,此地图将供希望探索悉尼这座城市的用户使用。实用地图项旨在直观展示所点击标记周围一定半径的区域。这样,用户便可以轻松了解从所点击的标记可以轻松步行至其他哪些目的地。

Maps JavaScript API 包括一组用于在地图上绘制形状(例如方形、多边形、线条和圆形)的函数。接下来,您将渲染一个圆形,当用户点击标记时,在该标记周围显示半径为 800 米(大约半英里)的区域。

  1. 使用 google.maps.Circle 绘制一个圆形。

    Maps JavaScript API 中的绘图函数提供各种选项,用于展现所绘对象在地图上的显示方式。若要渲染圆形半径区域,请声明一组圆形选项,例如颜色、笔触粗细度(此时圆形应该居中)以及半径,然后创建新 google.maps.Circle 实例以绘制新圆形:
     function drawCircle(map, location) {
       const circleOptions = {
         strokeColor: '#FF0000',
         strokeOpacity: 0.8,
         strokeWeight: 1,
         map: map,
         center: location,
         radius: 800
       }
       const circle = new google.maps.Circle(circleOptions);
       return circle;
     }
    
  2. 当用户点击标记时绘制圆形区域。

    若要在用户点击标记时绘制圆形区域,您只需要从 addPanToMarker() 中的点击监听器回调中调用上面编写的 drawCircle() 函数,并向其传递标记的地图和位置即可。

    请注意,还要添加用于调用 circle.setMap(null) 的条件语句。如果用户点击其他标记,该语句会从地图中移除之前渲染的圆形区域,因此,当用户浏览地图时,就不会最终显示被圆形区域覆盖的地图。

    您的 addPanToMarker() 函数应如下所示:
     function addPanToMarker(map, markers) {
       let circle;
       markers.map(marker => {
         marker.addListener('click', event => {
           const location = { lat: event.latLng.lat(), lng: event.latLng.lng() };
           map.panTo(location);
           if (circle) {
             circle.setMap(null);
           }
           circle = drawCircle(map, location);
         });
       });
     }
    

全部完成了!转到浏览器,然后点击某个标记。您应该会看到该标记周围渲染了圆形半径区域:

254baef70c3ab4d5.png

11. 恭喜

您使用 Google Maps Platform 成功构建了首个 Web 应用,包括加载 Maps JavaScript API、加载地图、使用标记、控制地图和在地图上绘图,以及添加用户互动。

要查看已完成的代码,请在 /solutions 目录中查看完成的项目。

后续操作

在此 Codelab 中,您了解了可以使用 Maps JavaScript API 执行的操作方面的基础知识。接下来,请尝试为地图添加下面的部分地图项:

  • 更改地图类型,以显示卫星地图、混合地图和地形地图。
  • 启用本地化,以不同的语言加载地图。
  • 自定义其他用户互动,例如缩放和地图控件
  • 添加信息窗口,以便在用户点击标记时显示信息。
  • 了解适用于 Maps JavaScript API 的其他,通过这些库可实现更多功能,例如地点、绘图和可视化。

要继续了解使用网页版 Google Maps Platform 的更多方式,请访问以下链接: