基于高德地图开发 Web 应用

拿我格子衫来 发表于 2022/03/17 23:25:57 2022/03/17
【摘要】 文章目录 写在前面为什么选择高德地图?对比腾讯、百度、OpenLayersOpenLayers腾讯地图百度地图高德地图 基本的开发步骤,开始实现自己的地图应用快速掌握 API 模块、架构、...

写在前面

前段时间换了工作,从以前的 996 变成了现在的 965,周末有了一些空闲时间,于是就想着写一些文章和大家分享一下。思考了很久,最终确定了主题为前端高德地图的教程。

这是一个比较宽泛的主题,而且高德地图的官网文档以及 API 实例已经真的是做得很好了,自己再去写一个教程出来,很难不和官网重复。所以我这篇 Chat,除了简单介绍高德地图的入门教程,更重要的是介绍整个框架,以及遇到不同种类的 LBS 需求改如何去做,思考的路线是如何,快速去实现它。

当然由于笔者水平有限,欢迎各位看官一起来讨论,学习。

这里我先解释一下一个名词 LBS:

LBS(Location Based Service)基于位置的服务,是利用各类型的定位技术来获取定位设备当前的所在位置,通过移动互联网向定位设备提供信息资源和基础服务。我们所使用的高德地图,路线搜索、自定定位、地图标记、导航、室内地图、定位,这些都是基于 LBS 做出来的。可以说 LBS 与我们的生活息息相关。

另外,本篇的技术栈是高德地图 JSAPI,属于前端范畴。

下面进入正题。

为什么选择高德地图?对比腾讯、百度、OpenLayers

目前做 LBS 需求的前端有几个 API 选择,高德地图、腾讯地图、百度地图,还有一个由于某些原因相对用的人比较少的 OpenLayers。

下面我就来简单说一下几个 SDK 的区别,同时也借鉴了一些网上的资源。

先说下很多人不熟悉的 OpenLayers。

OpenLayers

先放个官网:https://openlayers.org/

在这里插入图片描述

打开链接,首先映入眼帘的是全站的英文,光看这一眼,就丢失一批国内翻译都要靠有道的 IT 有志青年。看一下百度百科的介绍:

OpenLayers 是一个专为 Web GIS 客户端开发提供的 JavaScript 类库包,用于实现标准格式发布的地图数据访问。

再看下官网的介绍:

OpenLayers makes it easy to put a dynamic map in any web page. It can display map tiles,vector data and markers loaded from any source. OpenLayers has been developed to further the use of geographic information of all kinds. It is completely free,Open Source JavaScript,released under the 2-clause BSD License (also known as the FreeBSD)。

OpenLayers 使在任何 Web 页面中放置动态地图变得很容易。它可以显示从任何源加载的地图块、矢量数据和标记。OpenLayers 的开发是为了进一步利用各种地理信息。它是完全免费的、开源的 JavaScript,以句 BSD 许可(也称为 FreeBSD)发布。地图渲染方式为 Canvas 和 WebGL。

网站并不大,只有四个模块,文档、API、示例、代码。

这个库在所有的地图库中是最灵活的,也是最原始的,只提供了很基础的地图操作 API,缩放、坐标、标记、加载图层、面向对象。

由于面向对象,并且是开源的,所以库本身是非常易于定制和扩展的。

可以瞅一眼 OpenLayers 的框架架构:

OpenLayers 的框架架构

(图片来源于网络)

如果想要对 GIS、LBS 非常感兴趣,OpenLayers 真是一个不错的选择,不过学习难度有点高,文档都是英文的,并且官网有些案例打开的很慢。

接着在说一下腾讯地图。

腾讯地图

其实这个库我是真的没用过,看了一下官网:

https://lbs.qq.com/webApi/javascriptV2/jsGuide/jsOverview

腾讯地图 SDK 概述

又查了一些资料。很多服务型 API,如路线规划、距离计算都是要调用 HTTP 的接口,而不是和类库直接发起了,甚至有些参数还需要用户手动进行 URL 编码,使用 encodeURI。

目前的 JSAPI 是 2019-01-14 日更新的 v2.4.1.111,看了是好久没更新了啊。

其实腾讯地图 App 还是有不少人使用的,只是这个 JSAPI 实在用的很不多。有朋友知道用过的也可以多和我讨论讨论。

百度地图

JSAPI 传送门,目前是 3.0:

http://lbsyun.baidu.com/index.php?title=jspopular3.0

在这里插入图片描述

目前的版本是 2017 年 12 月 27 日上线的 V3.0,功能要比腾讯地图完整一些,有些功能和控件还是要借助其他的库,如点聚合过程需要加载 TextIconOverlay 和 MarkerClusterer 这两个类,有些时候,类之间的调用有很多 Bug,之前就遇到个图层显示不出来的问题。

示例和文档都要比腾讯的齐全,完整.很多人在选择地图类库的时候,往往看这个功能的平台以及相似功能的实例,比如小程序的有很多是使用腾讯,在做地图图表时,常常使用 EChart 搭配百度地图。各家推荐各家的产品,这也是人之常情。但作为开发的我们,只有选择最合适,最趁手的工具,才能把事情做得又快又好。

高德地图

高德之前是一家独立的公司,2002 年成立,2010 年上市,后来在 2014 年被阿里巴巴收购。

高德地图 JSAPI 最新版本是 2020-05-12 发布的 V2.0,从更新日志上来看,API 的更新还是比较频繁的,大部分是性能优化和开发新的特性,兼以 Bug 的修复。官方已经提供 JSAPI Loader 加载器和提供 TypeScript 声明,对于前端开发更方便,快捷,规范了。高德地图还有数据可视化的 API,叫做 loca-api 完完全全就是在地图上玩大数据、路径、热力图,相关示例可以查看:

https://lbs.amap.com/demo-center/loca-api

目前使用高德的有很多案例,不管从数据、市场和服务,都是一流的。

在这里插入图片描述

综合比较,高德地图是目前国内前端开发使用最广的地图 API,也是目前功能最完善、文档最详细、丰富的地图 API,有任何基于 LBS 的应用,首选高德就对了。

基本的开发步骤,开始实现自己的地图应用

为了照顾一些初接触前端的开发者,我这里增加了一章节 5 分钟教程。便于大家快速体验效果。

使用高德地图需要申请 appkey,有了 appkey 才能调用其 JS 的 SDK,每个 appkey 是不同限制的。

  • 申请 appkey 申请地址在此页面,先创建应用,在点击添加,增加一个 Web 端 JSAPI 的 key
  • 使用 key 引用 JS,调用 SDK

直接复制一下代码,保存为 HTML,浏览器打开,即可正常显示效果。此处使用的是我的 appkey:6d715cd10a703544388c24c35e7e89d6。

代码如下:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0,user-scalable=no,width=device-width">
    <title>地图加载完成事件</title>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css"/>
    <style>
        html,body,#container{
            height:100%;
            width:100%;
        }
    </style>

</head>
<body>
<div id="container"></div>
<div id="tip" class="info">地图正在加载</div>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=6d715cd10a703544388c24c35e7e89d6"></script>
<script type="text/javascript">
    //初始化地图对象,加载地图
    var map = new AMap.Map("container",{
        resizeEnable: true
    });
    map.on('complete',function() {
        document.getElementById('tip').innerHTML = "地图图块加载完毕!当前地图中心点为:" + map.getCenter();
    });
</script>
</body>
</html>


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

效果如下:

ddemo1 效果图

我们在 HTML 中引用 JS,地址为

https://webapi.amap.com/maps?v=1.4.15&key=6d715cd10a703544388c24c35e7e89d6

这是 1.4 版本,最新的是 2.0。key 就是我申请的 appkey。

使用 new AMap 去实例化一个地图的对象,第一个参数是一个 dom 的 id 或者是 dom 元素。

高德的 SDK 文档:

https://lbs.amap.com/api/javascript-api/reference/core

所有的官方示例:

https://lbs.amap.com/api/javascript-api/example/map-lifecycle/map-show

快速掌握 API 模块、架构、知识点思维导图

架构思维导图

一共有 20 个模块:

  • 基础类:经纬度、像素、边界、大小、这些是地图 JSAPI 开发必须了解的基本类型
  • 事件:地图 JSAPI 具有完备的事件体系,在 2.0 版本中所有类型的实例均使用 on/off 方法进行时间的绑定和移除
  • 地图:地图对象类,封装了地图的属性设置、图层变更、事件交互等接口的类。
  • 高德官方图层:由高德官方提供数据或图像的地图图层
  • 行业标准图层:符合 OGC 标准或者行业通行规范的的图层类型
  • 自有数据图层:用于加载展示开发者自己拥有的数据或者图像的图层类型
  • 点标记:用于在地图上添加点状地图要素的类型
  • 信息窗体:用于在地图上展示复杂的说明性信息的类型
  • 右键菜单:控制右键菜单
  • 矢量图形:用于在地图上绘制线、面等矢量地图要素的类型
  • 群组:用于批量操作图层和覆盖物的群组类型,可以简化代码书写
  • 地图控件:固定于地图最上层的用于控制地图某些状态的 DOM 组件类型
  • 工具类:用于满足一定专门功能的工具类型
  • 服务类:用于调用 Web 服务 API,直接透传查询条件和返回结果
  • 搜索:用于进行 POI 搜索联想与数据查询的相关类型
  • 地理编码:用于经纬度与地址之间的相互查询
  • 路线规划:用于驾车、货车、骑行、步行、公交等的路线规划查询
  • 其他服务:行政区查询、天气查询、公交站点和公交线路查询
  • 定位:用于进行城市定位或者精确定位的插件类型
  • 通用库:一些通用的函数库

最新的 JSAPI 2.0 的所有类的详解文档,请查看:

https://lbs.amap.com/api/jsapi-v2/documentation

关于直接获取此页面的所有类,只需要在页面下执行这段代码就能获取所有的类:

let arr = [];
[...document.querySelectorAll('.py1-ul li a.namespace')].forEach(x => {
  arr.push(x.innerText)
})
console.log(`一共有${arr.length}个模块`)
console.log(arr.join('\n'))

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取 SDK 所有类

如图,所有基于 LBS 的功能实现,都离不开这些类,直接看这些类,可能会有点抽象,所有大家学习的时候最好对比着官方提供的示例来看,图文结合。更好地了解每个 API 的真实效果。

除了要图文结合学习 SDK,还需要了解一些地图的基本的基础知识,不然你无法将你功能上的点无法映射到地图中的某个对象。

比如你的设计图上有一个这样的效果:

示例图

如果你了解地图的一些基本概念,就知道这是一个 Marker,好,那就找关于 Marker 的文档。看到 Marker 的文档后,你可以看到,Marker 可以设置对于经纬度的偏移量,为了不阻挡要看到的建筑或兴趣点,也可以社会 Marker 的 title 和 label。每个 Marker 都可以显示自己的信息内容。

除了 Marker 点标记之外还需要了解这些,地图容器、图层 Layers、矢量图形、地图控件、插件 Plugins、地图级别、经纬度、地图要素 Map Features(道路、区域面、POI 标注、路名……)等等。

这里官方都是有详细的解释:

https://lbs.amap.com/api/javascript-api/guide/abc/components

而其他的地图框架是没有这些解释的。

下面我就按照上面的学习方法以及文档搜索方法,来实现一个,滴滴打车选择上车地点的功能。

首先详解一下滴滴打车的选上车地点的功能:

  1. 打开页面后,地图自动定位到当前位置,
  2. 地图中心点有一个 Marker 表示,表示上车地点
  3. 拖动地图或缩放地图,重新定位上车地点显示出上车地点

功能细分后,我们需要去查询以下 API:

  • 地图的自动定位
  • 添加 Marker 并动态设置 Marker 的内容
  • 监听地图拖放,缩放事件
  • 根据地图中心查询地点位置

通过查询文档,我们需要翻阅以下几个模块的类:

  • 地理编码
  • 定位
  • 点标记
  • 地图
  • 事件

然后我们查询文档,可以得出一下的技术实现路线:

  1. 页面记载后,使用初始化地图,选择合适缩放比例,new AMap.Geolocation(options: GeolocationOptions) 进行自动定位,将地图中心设置为自定定位的经纬度。
  2. 然后添加在地图中心添加一个 Marker。
  3. 监听地图拖放,缩放事件 moveend zoomend,获取地图中心,移动 Marker。
  4. 获取最新的地址,设置 marker 的 label。

思索片刻,编码、调试一刻钟,于是就有了以下的代码:

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="initial-scale=1.0,user-scalable=no,width=device-width">
  <title>地图加载完成事件</title>
  <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
  <style>
    html,
    body,
    #container {
      height: 100%;
      width: 100%;
    }

    .amap-marker-label {
      border: 0;
      background-color: transparent;
    }

    .info {
      position: relative;
      top: 0;
      right: 0;
      min-width: 0;
    }

    .flex-center {
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .center-icon {
      position: fixed;
      z-index: 99;
      top: calc(50% - 31px);
      left: calc(50% - 9px);
    }
  </style>

</head>

<body>
  <img class="center-icon" src="https://webapi.amap.com/theme/v1.3/markers/n/mark_bs.png" />
  <div id="container"></div>
  <div id="tip" class="info">地图正在加载</div>
  <script type="text/javascript"
    src="https://webapi.amap.com/maps?v=1.4.15&key=6d715cd10a703544388c24c35e7e89d6&plugin=AMap.Geocoder"></script>
  <script type="text/javascript">
    //初始化地图对象,加载地图
    var map = new AMap.Map("container",{
      resizeEnable: true,
      zoom: 18
    });

    var marker = new AMap.Marker({
      // icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png",
      content: ' ',
      position: map.getCenter()
    });

    var geocoder = new AMap.Geocoder({
      // city: "010",//城市设为北京,默认:“全国”
      // radius: 500 //范围,默认:500
    });


    // 设置 label 标签
    // label 默认蓝框白底左上角显示,样式 className 为:amap-marker-label
    marker.setLabel({
      offset: new AMap.Pixel(-72,-40), //设置文本标注偏移量
      content: "<div class='info'>我是 marker 的 label 标签</div>",//设置文本标注内容
    });

    map.add(marker);

    //显示地图层级与中心点信息
    function logMapinfo() {
      var center = map.getCenter(); //获取当前地图中心位置

      geocoder.getAddress(center,function (status,result) {
        if (status === 'complete' && result.regeocode) {
          var address = result.regeocode.formattedAddress;

          marker.setLabel({
            offset: new AMap.Pixel(-72,-40), //设置文本标注偏移量
            content: `<div class='info'>${address}</div>`,//设置文本标注内容
          });

        } else {
          log.error('根据经纬度查询地址失败')
        }
      });

      marker.setPosition(center)
      marker.setAnimation('AMAP_ANIMATION_DROP')
    };

    //绑定地图移动与缩放事件
    map.on('moveend',logMapinfo);
    map.on('zoomend',logMapinfo);

  </script>
</body>

</html>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

复制代码保存 HTML,浏览器打开即可看到效果:

滴滴打车选上车位置

稍微解释一下这端代码。

为了获得更好的用户体验,也为了更加逼近真实的滴滴打车上车地点的选择,我使用了一个地图上方的虚假的图片来代替真实 Marker。真实的 Marker 是隐藏在其下面的,两者完全重叠。应该还有其他更好的方法,比如使用添加一个图层,将 Marker 的坐标在拖动地图时,相对于浏览器视口位置不动,始终垂直居中。如果有大佬出来指教,我将不耻下问。

当然了这里还有很多细节可以处理,比如 Marker 的样式、Marker 的 label、显示的长短,以及颜色都与原版不一致,大家就不要太纠结这些了。毕竟这里只是为了给大家演示一下接到需求后如何拆分、细化。查阅文档,制定技术细节,最终形成成品。

需要注意的是,这里有使用了一个经纬度查询地点的插件 AMap.Geocoder,使用方法就是在引入 SDK 是添加一个 plugin 的参数,如链接。

https://webapi.amap.com/maps?v=1.4.15&key=6d715cd10a703544388c24c35e7e89d6&plugin=AMap.Geocoder

  
 
  • 1

除此之外还有另一种使用办法:

AMap.plugin('AMap.Geolocation'function() {
  // 使用插件编写业务代码
})

  
 
  • 1
  • 2
  • 3

最后,拖拽地图选点,其实官方是有这样的组件的,使用起来非常方便。

点击链接查看

使用高德地图实现常见的地图效果

  1. 使用一个 URL,自动调取地图导航
  2. 展示省份的图层
  3. 显示一个城市的地铁线

使用一个 URL,自动调取地图导航

基本思路就是将经纬度当做参数,放在 URL 中,进入页面后,获取 URL 中的参数作为终点,与此同时,使用自动定位获取当前的经纬度,然后当做起点经纬度。然后调用 new AMap.Driving 去实例化一个搜索路径的示例。将起点和重点的经纬度传入,然后一条路线。核心代码

 <!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
  <title>地图加载完成事件</title>
  <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
  <style>
    html,
    body,
    #container {
      height: 100%;
      width: 100%;
    }

    .amap-marker-label {
      border: 0;
      background-color: transparent;
    }

    .info {
      position: relative;
      top: 0;
      right: 0;
      min-width: 0;
    }

    .flex-center {
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .center-icon {
      position: fixed;
      z-index: 99;
      top: calc(50% - 31px);
      left: calc(50% - 9px);
    }

    #panel {
      position: fixed;
      background-color: white;
      max-height: 90%;
      overflow-y: auto;
      top: 10px;
      right: 10px;
      width: 280px;
    }

    #panel .amap-call {
      background-color: #009cf9;
      border-top-left-radius: 4px;
      border-top-right-radius: 4px;
    }

    #panel .amap-lib-driving {
      border-bottom-left-radius: 4px;
      border-bottom-right-radius: 4px;
      overflow: hidden;
    }
  </style>


</head>

<body>
  <div id="container"></div>
  <div id="panel"></div>
  <script type="text/javascript"
    src="https://webapi.amap.com/maps?v=1.4.15&key=6d715cd10a703544388c24c35e7e89d6&plugin=AMap.Driving"></script>
  <script type="text/javascript">
    //初始化地图对象,加载地图
    var endPosition;
    function setEndPosition() {
      var lat = getQueryValue1('lat') // || 34.433988
      var lng = getQueryValue1('lng') // || 115.61957
      endPosition = new AMap.LngLat(lng, lat)
    }
    setEndPosition()
    var map = new AMap.Map("container", {
      resizeEnable: true,
      zoom: 18
    });

    AMap.plugin('AMap.Geolocation', function () {
      var geolocation = new AMap.Geolocation({
        enableHighAccuracy: true,//是否使用高精度定位,默认:true
        timeout: 10000,          //超过 10 秒后停止定位,默认:5s
        buttonPosition: 'RB',    //定位按钮的停靠位置
        buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
        zoomToAccuracy: true,   //定位成功后是否自动调整地图视野到定位点
      });
      map.addControl(geolocation);
      geolocation.getCurrentPosition(function (status, result) {
        if (status == 'complete') {
          onComplete(result)
        } else {
          onError(result)
        }
      });
    });

    //解析定位结果
    function onComplete(data) {
      console.log(data, '定位成功后的数据')
      startPosition = new AMap.LngLat(data.position.lng, data.position.lat)
      var str = [];
      str.push('定位结果:' + data.position);
      str.push('定位类别:' + data.location_type);
      if (data.accuracy) {
        str.push('精度:' + data.accuracy + ' 米');
      }//如为 IP 精确定位结果则没有精度信息
      str.push('是否经过偏移:' + (data.isConverted ? '是' : '否'));
      console.log(str.join('<br>'));

      startDriveLine(startPosition, endPosition)
    }

    //解析定位错误信息
    function onError(data) {
      console.log('定位失败', data)
    }

    function getQueryValue1(queryName) {
      var reg = new RegExp("(^|&)" + queryName + "=([^&]*)(&|$)", "i");
      var r = window.location.search.substr(1).match(reg);
      if (r != null) {
        return decodeURI(r[2]);
      } else {
        return null;
      }
    }

    function startDriveLine(start, end) {
      //构造路线导航类
      var driving = new AMap.Driving({
        map: map,
        panel: "panel"
      });
      // 根据起终点经纬度规划驾车导航路线
      driving.search(start, end, function (status, result) {
        // result 即是对应的驾车导航信息,相关数据结构文档请参考  https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
        if (status === 'complete') {
          console.log('绘制驾车路线完成')
        } else {
          console.error('获取驾车数据失败:' + result)
        }
      });
    }

  </script>
</body>

</html>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157

需要注意此功能需要的插件,AMap.Driving、AMap.Geolocation。如

http://192.168.0.105:8000/?lat=34.433988&lng=115.61957

url 导航

展示省份的图层

有时候我们不需要根据展示地图的河流、街道、地点,只需要显示省份的轮廓,这个时候我们就可以行政区图了,主要用到的是这个类 AMap.DistrictLayer 可以满足日常的行政区块的数据可视化、行政区边界展示。

如下面这种效果:

简单的行政区图

以下是核心代码:

<script language="javascript"
    src="https://webapi.amap.com/maps?v=2.0&key=6d715cd10a703544388c24c35e7e89d6&plugin=Map3D,AMap.DistrictLayer,AMap.Scale,AMap.ToolBar"></script>
  <script type="text/javascript" src="https://a.amap.com/jsapi_demos/static/demo-center/data/china-pp.js"></script>
  <script type="text/javascript">

    var SOC = 'CHN'
    var colors = {};
    var GDPSpeed = {
      '520000': 10,//贵州
      '540000': 10,//西藏
      '530000': 8.5,//云南
      '500000': 8.5,//重庆
      '360000': 8.5,//江西
      '340000': 8.0,//安徽
      '510000': 7.5,//四川
      '350000': 8.5,//福建
      '430000': 8.0,//湖南
      '420000': 7.5, //湖北
      '410000': 7.5,//河南
      '330000': 7.0,//浙江
      '640000': 7.5,//宁夏
      '650000': 7.0,//新疆
      '440000': 7.0,//广东
      '370000': 7.0,//山东
      '450000': 7.3,//广西
      '630000': 7.0,//青海
      '320000': 7.0,//江苏
      '140000': 6.5,//山西
      '460000': 7,// 海南
      '310000': 6.5,//上海
      '110000': 6.5, // 北京
      '130000': 6.5, // 河北
      '230000': 6, // 黑龙江
      '220000': 6,// 吉林
      '210000': 6.5, //辽宁
      '150000': 6.5,//内蒙古
      '120000': 5,// 天津
      '620000': 6,// 甘肃
      '610000': 8.5,// 甘肃
      '710000': 2.64, //台湾
      '810000': 3.0, //香港
      '820000': 4.7 //澳门

    }
    var getColorByDGP = function (adcode) {
      if (!colors[adcode]) {
        var gdp = GDPSpeed[adcode];
        if (!gdp) {
          colors[adcode] = 'rgb(227,227,227)'
        } else {
          var r = 3;
          var g = 140;
          var b = 230;
          var a = gdp / 10;
          colors[adcode] = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
        }
      }
      return colors[adcode]
    }

    var disCountry = new AMap.DistrictLayer.Country({
      zIndex: 10,
      SOC: 'CHN',
      depth: 1,
      styles: {
        'nation-stroke': '#ff6600',
        'coastline-stroke': 'ff8800',
        'province-stroke': 'white',
        'fill': function (props) {
          return getColorByDGP(props.adcode_pro)
        }
      }
    })
    console.log(disCountry, 'disCountry')

    var map = new AMap.Map("container", {
      zooms: [4, 10],
      center: [106.122082, 33.719192],
      zoom: 4,
      isHotspot: false,
      defaultCursor: 'pointer',
      layers: [
        disCountry
      ],
      viewMode: '2D',
      resizeEnable: true
    })
    map.addControl(new AMap.Scale());
    map.addControl(new AMap.ToolBar({ liteStyle: true }));
    map.on('complete', function () {
      var layer = new AMap.LabelsLayer({
        // 开启标注避让,默认为开启,v1.4.15 新增属性
        collision: false,
        // 开启标注淡入动画,默认为开启,v1.4.15 新增属性
        animation: true,
      });
      for (var i = 0; i < LabelsData.length; i++) {
        var labelsMarker = new AMap.LabelMarker(LabelsData[i]);
        labelsMarker.on('click', function(e){
          console.log(labelsMarker)
          // labelMarker.setOpacity(0.5);
        });

        layer.add(labelsMarker);
      }
      map.add(layer);
    })


  </script>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

官方提供的 API 可以支持,修改填充颜色和行政区的描边。
需要注意的是 每一个行政区都需要一个唯一标识,adcode 官方有提供 行政区对应的 ascode

显示一个城市的地铁线

如果要显示一个城市的地铁图,官方也是提供了不一样的 API,与地图 SDK 是不一样的。

地图的 SDK 链接是这样的:

https://webapi.amap.com/subway?v=1.0&key=6d715cd10a703544388c24c35e7e89d6&callback=cbk

  
 
  • 1

注意看 URL 中有一个 subway、key 和 callbanck。cbk 就是 SDK 加载完成后,需要执行的函数。

下面这段代码就是显示上海的地铁图:

<html>

<head>
  <meta charset="UTF-8">
  <!--重要 meta, 必须!-->
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,shrink-to-fit=no" />
  <title>SUBWAY</title>
</head>

<body>
  <div id="mysubway"></div>
  <script src="https://webapi.amap.com/subway?v=1.0&key=6d715cd10a703544388c24c35e7e89d6&callback=cbk"></script>
  <script type="text/javascript">
    //开启 easy 模式, 直接完成地铁图基本功能, 无需自己写交互
    window.cbk = function () {
      var mysubway = subway("mysubway", { easy: 1, adcode: 3100 });
    };
  </script>
</body>

</html>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

效果图:

上海地题图

生成的地图可以拖动,可以选择起点终点,进行地图路线规划,同时我们也可以添加标记:

mysubway.addMarker('南锣鼓巷');

  
 
  • 1

高德地图在各个框架里的使用

在之前单页面项目中,地图 SDK 的引入,我们可以在根目录 index.html 中直接引入,也可以在组件里引入,但看起来都不是很规范。

于是高德地图在 2.0 的时候,提供一个官方的 SDK 加载方式,使用 JSAPI Loader 来加载高德地图 SDK。

具体方式如下:

npm i @amap/amap-jsapi-loader --save-dev

  
 
  • 1

安装依赖包:

import AMapLoader from '@amap/amap-jsapi-loader';
AMapLoader.load({
  "key": "您申请的 key 值", // 申请好的 Web 端开发者 Key,首次调用 load 时必填
  "version": "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  "plugins": [] //插件列表
}).then((AMap) => {
  map = new AMap.Map('container');
}).catch(e => {
  console.log(e);
})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

以上是高德地图 SDK 在单页面应用中的使用,除此之外,在小程序中使用也可以使用此方法。

在微信小程序中使用高德 SDK 是比较麻烦的,因为小程序限制不能加载外部的脚本,并且不能使用 dom 接口。

所有需要将 SDK 下载到项目中:

高地地图微信小程序 SDK 下载地址

首先需要先申请一个微信小程序的 SDK 的 appkey:

在这里插入图片描述

将 SDK 下载项目目录里,像这样子引用:

var amapFile = require('../../sdk/amap-wx.js');//如:..­/..­/libs/amap-wx.js

  
 
  • 1

Demo 的核心代码如下:

var amapFile = require('../../sdk/amap-wx.js');//如:..­/..­/libs/amap-wx.js
var markersData = [];
Page({
  data: {
    markers: [],
    latitude: '',
    longitude: '',
    textData: {}
  },
  makertap: function(e) {
    var id = e.markerId;
    var that = this;
    that.showMarkerInfo(markersData,id);
    that.changeMarkerColor(markersData,id);
  },
  onLoad: function() {
    var that = this;
    var myAmapFun = new amapFile.AMapWX({key:'fee03d59db0d38196582cf0cbb734e05'});
    myAmapFun.getPoiAround({
      iconPathSelected: '选中 marker 图标的相对路径', //如:..­/..­/img/marker_checked.png
      iconPath: '未选中 marker 图标的相对路径', //如:..­/..­/img/marker.png
      success: function(data){
        markersData = data.markers;
        that.setData({
          markers: markersData
        });
        that.setData({
          latitude: markersData[0].latitude
        });
        that.setData({
          longitude: markersData[0].longitude
        });
        that.showMarkerInfo(markersData,0);
      },
      fail: function(info){
        wx.showModal({title:info.errMsg})
      }
    })
  },
  showMarkerInfo: function(data,i){
    var that = this;
    that.setData({
      textData: {
        name: data[i].name,
        desc: data[i].address
      }
    });
  },
  changeMarkerColor: function(data,i){
    var that = this;
    var markers = [];
    for(var j = 0; j < data.length; j++){
      if(j==i){
        data[j].iconPath = "选中 marker 图标的相对路径"; //如:..­/..­/img/marker_checked.png
      }else{
        data[j].iconPath = "未选中 marker 图标的相对路径"; //如:..­/..­/img/marker.png
      }
      markers.push(data[j]);
    }
    that.setData({
      markers: markers
    });
  }

})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

以上是核心代码,完整代码请查看这里

Demo 截图:

在这里插入图片描述

写在最后

文章到这里就算写完了,文中有哪些不清楚,或不够完善的,都可以加我微信来咨询我 demon_0212,谢谢大家了。


本文首发于 GitChat,未经授权不得转载,转载需与 GitChat 联系。

文章来源: fizzz.blog.csdn.net,作者:拿我格子衫来,版权归原作者所有,如需转载,请联系作者。

原文链接:fizzz.blog.csdn.net/article/details/119764361

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。