前言
本文作为笔者初上手地图类需求开发的小记,没有深入的探讨,仅包含了一些初级API使用的记录与一些萌新踩坑的总结。
需求简述
产品给提了一个需求,需要用到高德地图组件将一组或多组经纬度坐标在地图中描绘出来,同时会有一系列的交互上的设计,功能整体而言其实不多——一个地图加一个列表,需要在地图上绘制多个多边形,列表里的每一条记录会对应一个描点,鼠标覆盖某一记录时描点高亮,反之亦然。
前期准备
将页面整体分为两个部分:
1、地图
2、列表:用绝对定位的方式在页面上布局,确定列表的位置。
地图处理:
由需求而言,在地图上的处理其实仅需增加多边形、描点、信息窗体即可,交互上大量调用API和使用监听事件。
资料:
高德地图:WebAPI概述
高德地图:覆盖物
高德地图:信息窗体
组件引入
项目中已有类似的例子,所以插件引入方面投入工作量基本为零,直接“上手开发”。 通过npm安装或JS引入项目的方式,引入高德地图插件。
加载地图
由准备中的计划,页面上放一个指定ID的容器用作加载地图,通过样式控制容器的宽高,在实例化地图时,传入这个ID,同时设置地图的中心点,缩放层级zoom等属性。
var map = new AMap.Map('ID', {
// 地图中心位置,(用了官网示例的地址)
center:[117.000923,36.675807],
// 缩放级别,是一个范围,2.0版本貌似扩展到 2-20
zoom:11,
// ...
});
// 挂到上下文里去更方便使用 this.map = XXX;
加载多边形
调用高德提供的API,将后端同学提供的经纬度直接绘制到地图上。
let polygon = new AMap.Polygon({
// 路径是一个二维数组;
path: [[lng, lat], ...],
// 样式的基本设置;
...
// 冒泡到地图上:默认false,Boolean类型;
bubble: false,
// 地图实例:之前创建的地图实例,this.map;
map: this.map,
// 用户自定义类型,Any;
extData: {
// 个人觉得这一属性太有用了...
},
});
描点Marker&信息窗体infoWindow
太少写类似的笔记了,感觉都写的跟搬官网的似的,实例化过程就试着不记载了吧,挂一下官网的覆盖类文档——高德地图:覆盖类
开发过程小记
咋一看需求不多,好像就两个功能点,但实现起来确实花了不少脑子,有走弯路,好在文档很全面,耐心看,某个属性就能帮忙解决棘手的问题。
自定义属性extData
地图上的覆盖物实在太多了,一个多边形N个描点,一个描点一个信息窗体,想要方便快捷获取对应的数据,在实例化覆盖物对象时,就将对应的自定义信息捆绑,找到覆盖物就能拿到想要的信息,不必再额外想办法去存取。
// 获取自定义信息
map.getExtData();
// 设置自定义信息
map.setExtData()
当然这主要是在引用的时候进行操作,在实例化的时候就可以挂到extData属性下面,多边形、描点都有这个属性,或者说覆盖物都有这个属性。
let polygon = new AMap.Polygon({
...
extData: {
// Any类型
},
...
});
取某一个覆盖物
目前想到的方法是取某一类的覆盖物,再从自定义属性里去查询,这么做是因为恰好,在需求里多边形有一个对应唯一的ID,描点也有一个独立的唯一的ID,同样信息窗体也是。再遇到非此类情况的再想办法吧……覆盖物实例里有一个自己的ID,用这个ID去查询也是一个好办法吧。
/*
* 括号内不传参的话,会获取全部的覆盖物,可以传入一个类型
* 参数类型是字符串,如多边形、描点等
*/
this.map.getAllOverLays();
/**
* 返回的值是一个数组,可以用for循环遍历
* 遍历过程中就可以去查特定的一个覆盖物
*/
this.map.getAllOverLays().forEach( map => {
if (map.getExtData().extData === "") {
// do ...
}
});
/**
* 注意获取额外信息时,类型是任意的,取值方式留意一下
*/
移除覆盖物
可以通过map.remove方法移除一个或多个覆盖物,传入的参数是覆盖物实例,需要一次移除多个覆盖物时,需要以数组的形式传入
// 移除一个描点marker
map.remove(marker);
// 一次性移除一个marker和一个多边形polygon
map.remove([marker, polygon]);
获取覆盖物范围
// 以多边形为例,获取一个范围
polygon.getBounds();
/**
* 拿到的是一个范围,在这里面还可以拿到想要的经纬度
*/
判断是否点在当前多边形内
// 判断即将绘制的点是否在指定区域内
polygon.contains(point: LngLat);
/**
* 返回的是一个Boolean,接收参数是一个坐标,根据坐标判断是否在当前多边形范围内,坐标的类型需要是LngLat
*
* 可以避免在指定范围外绘制
*/
LngLat类
经纬度坐标,确定地图上的一个点。(官方文档)
可以用于构造经纬度坐标对象,方便更好的在地图上确定一个坐标。当需要传入一个坐标时,最好构建一个LngLat实例。
const lngLat = new AMap.LngLat(lng:Number,lat:Number,noAutofix:bool);
/**
* Lng::经度
*
* Lat:纬度
*
* noAutofix:是否自动将经度修正到 [-180,180] 区间内,默认值是false,
*/
SetFitView的使用
让指定地图实例或覆盖物出现在视野中居中的位置,会自动调整一个合适的zoom和中心点。
map.setFitView()
// 不传则会把所有的覆盖物调整到合适的位置上
// 传入一个实例,则只会调整一个
// 想要调整多个,传入一个数组
挖坑记录
事件监听的绑定与移除
事件的监听和移除声明时需要完全一致,否则会没办法移除事件的监听。想要绑定上下文对象,使用第三个参数即可,不必在第二个参数处用bind之类的方法去绑定。
map.on('type', method, context);
及时更新自定义的数据
在项目中,由于使用了大量的自定义数据,起初没有及时更新,导致在数据处理的时候出现了没有改变的情况,尤其是自定义数据来源于某一个经常变化的数组。
// 简述
// 从请求中拿到一个人员列表
userList: [ ... ];
// 绑定到自定义数据上
const poylgon = new AMap.Polygon({
...
extData: {
userList,
},
...
});
// 过程中对列表进行了操作改变了列表原有的数据,更新自定义数据
polygon.setExtData({
userList: updatedUserList,
});
信息窗体的样式名
其实是一个HTML字符串,得用class,所以不要用混了,以react为例,记得不要习惯性用了className,
Scc
GitHub:Young(反正是家徒四壁)