vue 接入天地图并且在地图上画基站扇形覆盖物
vue接入天地图倒是不难,但是要在地图上画扇形倒是有点点麻烦。
为什么选择天地图呢,因为百度地图或者是高德地图在定位的时候都会使用自家的算法在经纬度信息上进行加密,所以说与实际有很大的差距,但是天地图比较专业,当然也有瑕疵了,在天地图开发过程中就会发现,呵呵,个性化的东西就是不如商业气息浓厚的百度地图做的精致。
vue接入天地图
其实天地图和百度地图的用法类似,根据官方提供的文档和案例可是实现很多的功能,然后在vue里面使用的话也很简单。
首先需要开发者创建一个应用,然后获取一个应用的 token。
然后就简单了,只需要在 vue 项目的 index.html 文件中引入天地图。
<script src="https://api.tianditu.gov.cn/api?v=4.0&tk=这里是你申请的key" type="text/javascript"></script>
好了,引完了,就可以直接开发了。
创建一张天地图地图
首先在我们需要创建地图的页面添加一个div用来放置地图。
<div id="mapDiv"></div>
注意:这个div需要设置高度和宽度,否则地图显示不出来哈!
然后写ts代码就可以了,会vue的话看得懂,有些声明自己声明一下,我这里写关键代码哈。
initMap() {
map = new T.Map("mapDiv");
map.centerAndZoom(new T.LngLat(116.40769, 39.89945), 15); //地图的初始化中心点,此为北京的经纬度
map.setMinZoom(5); // 设置地图缩放比
map.setMaxZoom(18); // 设置地图缩放比
}
这样,地图就展示出来了!
地图缩放
这个就很简单了,文档写的很清楚,放大或缩小就一行代码。
map.zoomIn() // 区域放大地图
map.zoomOut() // 区域缩小地图
可以写两个按钮,然后按照需要,分别执行上面两行代码。
测距
测量距离的话,官网案例也写的很详细。
首先需要在地图创建完成之后,创建一个测量工具。
lineTool = new T.PolylineTool(map, {
showLabel: true
});
然后我们可以写一个按钮,点击执行开始测距功能。
lineTool.open() // 开始测距
测量面积
测面积和测距差不多。
首先需要创建一个测量面积的工具。
polygonTool = new T.PolygonTool(map, {
showLabel: true,
color: "#4aa8b0", weight: 3, opacity: 0.5, fillColor: "#9dd8d2", fillOpacity: 0.5
});
然后写一个按钮,点击就执行开始测面积的方法。
polygonTool.open() // 开始测面积
当然,无论是测面积还是测距离,看官方文档,可以设置线的颜色、粗细等,具体查找官方文档哈!
鼠标移动地图,获取地图可视范围
这个就是鼠标移动地图之后,我想知道地图范围是从多少到多少,或者是当前缩放比例是多少,其实不难,就是监听一下移动结束事件。
map.addEventListener("moveend", (e) => {
let zoom = map.getZoom(); // 当前地图缩放等级
let bs = map.getBounds();
let bssw = bs.getSouthWest(); //可视区域左下角经纬度
let bsne = bs.getNorthEast(); //可视区域右上角经纬度
}); // 获取鼠标移动结束事件
获取到之后,我们可以根据需要处理一下然后展示在界面上。
这个根据自己的需要随便设计,无所谓的都。
绘制点
然后绘制点啥的直接看官方文档就可以,写的十分的详细,也是没有很大问题的,当然了,当覆盖物太多也会卡顿,如果是渲染单纯的点,可以使用海量点,使用海量点的话就不能点击啥的,样式也不能自定义,只是单纯的点。
绘制基站扇形覆盖物
绘制扇形是这个样子,需要有中心点经纬度信息,每个扇形偏转信息,扇形的半径信息。我这个效果图的弧度是默认30°的。我的效果就是下面的图的样子,如果你们要做的不是这个样子,那就抓紧退出,别看错了哈。我这个图画出来会随着缩放同时放大缩小,和坐标点不一样的。
数据准备
首先我们需要一些模拟数据,我这边是这样的哈
红框标出来的是一个基站的数据,x标识经度,y标识纬度,name标识基站名称,data是一个列表,里面包含着多个扇区,每一个扇区包含一个 r 表示偏转角度,msg表示扇区的名称,其实也可以添加一个半径,我默认一公里了,也就是1000米。
开始绘制扇形
首先我们创建一个方法遍历这些数据开始一个一个的绘制基站,list表示模拟数据列表。
this.list.forEach(element => {
this.makeSectors(element)
});
调用了makeSectors方法,这个方法绘制一个基站
makeSectors(mapPoints) {
// 遍历基站的扇区
for (var i = 0; i < mapPoints.data.length; i++) {
let point = new T.LngLat(mapPoints.x, mapPoints.y); // 基站点的位置,也就是扇区的尖
let azimuth1 = 90 - mapPoints.data[i].r - 15 // 旋转角度是扇区中间,我默认30°,一半是15°
let azimuth2 = 90 - mapPoints.data[i].r + 15 // 同上边
// 然后画扇形的覆盖物,调用了Sector1方法
let oval = new T.Polygon(this.Sector1(point, 500, azimuth1, azimuth2, "wjw"), {
color: "blue",
weight: 1,
opacity: 0.6,
fillColor: "#ff7200",
fillOpacity: 0.6
});
map.addOverLay(oval);
var info = []; // 给每个扇形添加一个信息框,点击弹出
info.push("<b>名称:</b>" + mapPoints.name);
info.push("<b>经度:</b>" + mapPoints.x);
info.push("<b>纬度:</b>" + mapPoints.y);
info.push("<b>扇区信息:</b>" + mapPoints.data[i].msg);
info.push("<b>扇区转角:</b>" + mapPoints.data[i].r + ' °');
let content = info.join("<br/>");
this.addClickHandler(content, oval); //调鼠标用点击事件
this.addMouseOver(oval);//调鼠标悬停事件
this.addMouseOut(oval);//调用鼠标离开事件
}
},
Sector1方法
// 获取扇形坐标点
Sector1(point2, radius, sDegree, eDegree, opts) {
let points = []; //创建构成多边形的点数组
let step = ((eDegree - sDegree) / 10) || 10; //根据扇形的总夹角确定每步夹角度数,最大为10
points.push(point2);
for (let i = sDegree; i < eDegree + 0.001; i += step) { //循环获取每步的圆弧上点的坐标,存入点数组
points.push(this.EOffsetBearing(point2, radius, i));
}
points.push(point2);
if (sDegree == eDegree) {
let planepoint = points[1];
let marker = new T.Marker(planepoint);
let opts = {
width: 200, // 信息窗口宽度
height: 100, // 信息窗口高度
title: "wjw", // 信息窗口标题
};
map.addOverLay(marker);
}
return points;
},
计算扇形坐标的方法
// 计算扇形坐标
EOffsetBearing(point3, dist, bearing) {
let lngConv = map.getDistance(point3, new T.LngLat(point3.lng + 0.1, point3.lat)) * 10; //计算1经度与原点的距离
let latConv = map.getDistance(point3, new T.LngLat(point3.lng, point3.lat + 0.1)) * 10; //计算1纬度与原点的距离
let lat = dist * Math.sin(bearing * Math.PI / 180) / latConv; //正弦计算待获取的点的纬度与原点纬度差
let lng = dist * Math.cos(bearing * Math.PI / 180) / lngConv; //余弦计算待获取的点的经度与原点经度差
return new T.LngLat(point3.lng + lng, point3.lat + lat);
},
鼠标移入扇形区的方法
// 鼠标移入扇形区
addMouseOver(oval) {
oval.addEventListener("mouseover", function () {
oval.setWeight(2);//边界变宽
oval.setOpacity(.8);//边界颜色变深
oval.setFillOpacity(.8);//填充颜色变深
});
},
鼠标移出扇形区的方法
// 鼠标移出扇形区
addMouseOut(oval) {
oval.addEventListener("mouseout", function () {
oval.setWeight(1);//边界恢复
oval.setOpacity(.6);//边界透明度变化
oval.setFillOpacity(.6);//填充颜色变化
});
},
点击扇区
addClickHandler(content, marker) {
let that = this
marker.addEventListener("click", function (e) {
that.openInfo(content, e);
});
},
打开信息弹窗
//打开信息弹窗
openInfo(content, e) {
let that = this
let point = e.lnglat;
that.marker = new T.Marker(point); // 创建标注 content
let markerInfoWin = new T.InfoWindow(content, {
offset: new T.Point(0, -20)
}); // 创建信息窗口对象
map.openInfoWindow(markerInfoWin, point); //开启信息窗口
},
然后就可以了!