vue基于高德地图实现城市管网压力点、管线、测距、测面积、绘制多边形、绘制圆代码
最近在研究城市管网gis系统是如何实现管网绘制的,于是基于高德地图研究了下管线和压力点、管线名称实现的逻辑,输出了一个简单的demo,最终效果如下:
1、定义标记点位
2、自定义绘制折线
3、绘制矩形
4、绘制多边形
5、绘制圆形
6、鼠标放大缩小
7、计算区域面积
8、测量距离
代码如下:
<template>
<div id="amapContainer"></div>
</template>
<script>
import { getAngle } from '@/utils/index.js';
export default {
name: 'amap3d',
data () {
return {
makers: [
{ Lng: 116.501415, Lat: 39.926055 },
{ Lng: 116.474605, Lat: 39.946324 },
]
};
},
mounted () {
this.intAmap();
},
methods: {
drawMap (city = '北京市', LngLats) {
const AMap = this.AMap;
const vm = this;
const opts = {
subdistrict: 0,
extensions: 'all',
level: 'city'
};
//利用行政区查询获取边界构建mask路径
//也可以直接通过经纬度构建mask路径
const district = new AMap.DistrictSearch(opts);
district.search(city, function (status, result) {
const bounds = result.districtList[0].boundaries;
const mask = [];
for (let i = 0; i < bounds.length; i += 1) {
mask.push([bounds[i]]);
}
const map = new AMap.Map('amapContainer', {
mask: mask,
center: [116.501415, 39.926055],
disableSocket: true,
viewMode: '2D',
showLabel: false,
labelzIndex: 130,
pitch: 0,
zoom: 15,
// mapStyle: "amap://styles/darkblue",
// 卫星地图显示
layers: [
// new AMap.TileLayer.RoadNet({
// //rejectMapMask:true
// }),
// new AMap.TileLayer.Satellite()
]
});
// 添加压力监测点
(LngLats || []).forEach(v => {
const position = new AMap.LngLat(v.Lng, v.Lat);
// 点标记显示内容,HTML要素字符串
const markerContent = '' +
`<div class="custom-content-marker zyc-marker-icon">
<img src="//a.amap.com/jsapi_demos/static/demo-center/icons/dir-via-marker.png">
<div class="content">
<p>1#压力点:1.24 Mpa</p>
<p>2#压力点:3.02 Mpa</p>
</div>
</div>`;
new AMap.Marker({
position: position,
// 将 html 传给 content
content: markerContent,
// 以 icon 的 [center bottom] 为原点
offset: new AMap.Pixel(-13, -30),
map: map // 添加到对应的map地图实例
});
});
// 添加管线
const path = vm.makers.map(v => [v.Lng, v.Lat]);
const polyline = new AMap.Polyline({
path: path,
isOutline: true,
outlineColor: '#ffeeff',
borderWeight: 1,
strokeColor: "red",
strokeOpacity: 1,
strokeWeight: 1,
// 折线样式还支持 'dashed'
strokeStyle: "solid",
// strokeStyle是dashed时有效
strokeDasharray: [10, 5],
lineJoin: 'round',
lineCap: 'round',
zIndex: 50,
});
map.add([polyline]);
// 添加管线名称
const textLng = (vm.makers[0].Lng + vm.makers[1].Lng) / 2;
const textLat = (vm.makers[0].Lat + vm.makers[1].Lat) / 2;
// 根据两个压力点计算管线的方位角
const textAngle = getAngle(vm.makers[0].Lng, vm.makers[0].Lat, vm.makers[1].Lng, vm.makers[1].Lat);
const text = new AMap.Text({
text: 'DN-125',
anchor: 'center', // 设置文本标记锚点
draggable: true,
cursor: 'pointer',
angle: textAngle + 90, // 必须要+ 90,不然名字和管线是垂直状态
style: {
'border-radius': '0',
'background-color': 'white',
'border-width': 0,
'box-shadow': '0 2px 6px 0 rgba(114, 124, 245, .5)',
'text-align': 'center',
'font-size': '10px',
'color': 'blue'
},
position: [textLng, textLat]
});
text.setMap(map); // 添加管线名称
});
},
// 地图初始化
intAmap (callBack) {
this.AMap = window.AMap;
this.AMap.plugin(['AMap.MouseTool', 'AMap.PolyEditor', 'AMap.ControlBar', 'AMap.DistrictSearch', 'Map3D', 'AMap.Object3DLayer'], function () {
//TODO 创建控件并添加
});
if (callBack && typeof callBack == 'function') {
callBack();
}
this.drawMap('北京市', this.makers);
}
}
};
</script>
<style lang="scss">
#amapContainer {
.custom-content-marker {
position: relative;
width: 25px;
height: 34px;
img {
width: 100%;
height: 100%;
}
.close-btn {
position: absolute;
top: -6px;
right: -8px;
width: 15px;
height: 15px;
font-size: 12px;
background: #ccc;
border-radius: 50%;
color: #fff;
text-align: center;
line-height: 15px;
box-shadow: -1px 1px 1px rgba(10, 10, 10, 0.2);
}
.close-btn:hover {
background: #666;
}
.content {
position: absolute;
left: 20px;
top: 10px;
height: 100px;
width: 200px;
background: rgba(10, 10, 10, 0.7);
p {
padding: 5px 10px;
color: #fff;
font-size: 14px;
text-align: left;
}
}
}
}
</style>
<style lang="scss" scoped>
#amapContainer {
height: 800px;
width: 100%;
margin: 0 auto;
}
</style>
两个经纬度之间计算角度
//计算旋转角度
export function getAngle( lon1, lat1, lon2,lat2) {
const deg2rad = Math.PI / 180;
const dlat = (lat2 - lat1) * deg2rad;
const dlon = (lon2 - lon1) * deg2rad;
const y = Math.sin(dlon) * Math.cos(lat2 * deg2rad);
const x = Math.cos(lat1 * deg2rad) * Math.sin(lat2 * deg2rad) - Math.sin(lat1 * deg2rad) * Math.cos(lat2 * deg2rad) * Math.cos(dlon);
const angle = Math.atan2(y, x) * 180 / Math.PI;
return angle;
}
绘制覆盖物
// 根据不同类型绘制不同覆盖物
drawTypeInt (type, mouseTool) {
switch (type) {
// 点标记
case 'marker': {
mouseTool.marker({
draggable: true,
//同Marker的Option设置
});
break;
}
// 折线
case 'polyline': {
mouseTool.polyline({
strokeColor: '#80d8ff'
//同Polyline的Option设置
});
break;
}
// 多边形
case 'polygon': {
mouseTool.polygon({
fillColor: '#00b0ff',
strokeColor: '#80d8ff'
//同Polygon的Option设置
});
break;
}
// 矩形
case 'rectangle': {
mouseTool.rectangle({
draggable: true,
fillColor: '#00b0ff',
strokeColor: '#80d8ff'
//同Polygon的Option设置
});
break;
}
// 圆形
case 'circle': {
mouseTool.circle({
draggable: true,
fillColor: '#00b0ff',
strokeColor: '#80d8ff'
//同Circle的Option设置
});
break;
}
// 放大
case 'zoomIn': {
mouseTool.rectZoomIn({
strokeColor: '#80d8ff',
fillColor: '#80d8ff',
fillOpacity: 0.3
//同 Polygon 的 Option 设置
});
break;
}
// 缩小
case 'zoomOut': {
mouseTool.rectZoomOut({
strokeColor: '#80d8ff',
fillColor: '#80d8ff',
fillOpacity: 0.3
//同 Polygon 的 Option 设置
});
break;
}
// 计算面积
case 'measureArea': {
mouseTool.measureArea({
strokeColor: '#80d8ff',
fillColor: '#80d8ff',
fillOpacity: 0.3
//同 Polygon 的 Option 设置
});
break;
}
case 'rule': {
// 测量尺
mouseTool.rule({
startMarkerOptions: {//可缺省
icon: new AMap.Icon({
size: new AMap.Size(19, 31),//图标大小
imageSize: new AMap.Size(19, 31),
image: "//webapi.amap.com/theme/v1.3/markers/b/start.png"
}),
offset: new AMap.Pixel(-5, -31)
},
endMarkerOptions: {//可缺省
icon: new AMap.Icon({
size: new AMap.Size(19, 31),//图标大小
imageSize: new AMap.Size(19, 31),
image: "//webapi.amap.com/theme/v1.3/markers/b/end.png"
}),
offset: new AMap.Pixel(-9, -31)
},
midMarkerOptions: {//可缺省
icon: new AMap.Icon({
size: new AMap.Size(19, 31),//图标大小
imageSize: new AMap.Size(19, 31),
image: "//webapi.amap.com/theme/v1.3/markers/b/mid.png"
}),
offset: new AMap.Pixel(-9, -31)
},
lineOptions: {//可缺省
strokeStyle: "solid",
strokeColor: "#FF33FF",
strokeOpacity: 1,
strokeWeight: 2
}
//同 RangingTool 的 自定义 设置,缺省为默认样式
});
}
}
},
// 切换覆盖物绘制
changeType (type) {
this.closeMouseTools();
this.drawTypeInt(type, this.mouseTool);
},
// 关闭鼠标编辑器
closeMouseTools () {
this.mouseTool.close(true);
this.clearAllMaker();
},
// 清空覆盖物
clearAllMaker () {
this.map.remove(this.overlays);
this.overlays = [];
this.$message.success('清除成功');
},
// 鼠标事件初始化
mouseInt (map = this.map) {
const vm = this;
const AMap = window?.AMap;
const mouseTool = new AMap.MouseTool(map);
//监听draw事件可获取画好的覆盖物
this.overlays = [];
mouseTool.on('draw', function (e) {
vm.overlays.push(e.obj);
console.log('----当前覆盖物对象---', e.obj);
});
this.mouseTool = mouseTool;
// 默认绘制点
vm.drawTypeInt('marker', mouseTool);
},