1 -效果图
2-TdtMap.vue
<template>
<div>
<div style="position: absolute; z-index: 1001">
<el-button v-if="isPolygon && isPolygon==true && openPolygon==false"
style="margin-left: 10px;margin-top: 3px;" size="small" type="primary" @click="startPolygon">开启绘制</el-button>
<el-button v-if="isPolygon && isPolygon==true && openPolygon==true"
style="margin-left: 10px;margin-top: 3px;" size="small" type="primary" @click="closePolygon">闭合绘制</el-button>
<el-button v-if="isPolygon && isPolygon==true" style="margin-top: 3px;" size="small" type="primary" @click="removePolygon">去除绘制</el-button>
<SearchComponent v-if="isSearch && isSearch==true" style="display: inline-block; margin: 3px 10px 2px 10px;" @select="handlerSelect" @selectAddress="handlerSelectAddress"></SearchComponent>
<el-button v-if="center" :style="'margin-top: 3px;'+(((isPolygon && isPolygon==true)||(isSearch && isSearch==true))?'':'margin-left: 10px;')" size="small" type="primary" @click="toVillage">前往村坐标</el-button>
</div>
<div ref="container" id="mapDiv" style="width: 100%; height: 500px"></div>
</div>
</template>
<script>
import SearchComponent from "./SearchComponent"
import axios from 'axios'
export default {
props: ['isPolygon', 'isSearch', 'isDbClick'],
components: { SearchComponent },
data() {
return {
center: undefined,
marker: undefined,
markers: [],
polygon: [],
closed: false,
tempPoints: [],
tempLines: new L.polyline([]),
tempNodes: [],
openPolygon: false,
dblclickTime: undefined,
moveSelected: {
feature: undefined,
originalColor: undefined,
selectedColor: 'rgba(200,200,200,0.8)',
},
defaultColor: 'rgba(155,155,155,0.15)',
coordinateWgs:[],
}
},
methods: {
mapClose() {
if (this.map != undefined) {
console.log('mapClose')
this.map.remove()
this.map = undefined;
this.center = undefined;
this.marker = undefined;
this.polygon = [];
this.closed = false;
this.tempPoints = [];
this.tempLines = new L.polyline([]);
this.tempNodes = [];
this.openPolygon = false;
this.dblclickTime = undefined;
this.moveSelected = {
feature: undefined,
originalColor: undefined,
selectedColor: 'rgba(200,200,200,0.8)',
};
this.defaultColor = 'rgba(155,155,155,0.15)';
}
},
mapInit(center, boundaryCoordinate) {
let that = this;
that.center = undefined;
this.$http({
url: "/sysregion/getMapData",
method: "get",
}).then(res => {
that.center = res.data.center;
let level = parseInt(res.data.level) ;
if (that.map == undefined) {
that.map = L.map("mapDiv", {
center: that.center,
zoom: level,
minZoom: 11,
maxZoom: level,
attributionControl: false,
zoomControl: false,
});
let map = that.map;
let layerGroup = [L.tileLayer(this.leafletMapUrl, {
maxZoom: level,
})]
if (res.data.tileLayer && res.data.tileLayer != '') {
let url = res.data.tileLayer;
if (url.indexOf('png') >= 0) {
layerGroup.push(L.tileLayer(res.data.tileLayer, {
bounds: res.data.bounds,
maxZoom: level,
tms: true,
}))
} else {
layerGroup.push(L.tileLayer(res.data.tileLayer + "/{z}/{y}/{x}.png", {
bounds: res.data.bounds,
maxZoom: level,
}))
}
}
layerGroup.push(L.tileLayer(this.annotationMapUrl, {
}))
L.layerGroup(layerGroup).addTo(map)
if (res.data.geoLayer && res.data.geoLayer != '') {
this.$http({
url: "/sysregion/jsonData",
method: "post",
data: { geoLayer: res.data.geoLayer }
}).then(res => {
let json = JSON.parse(res.data)
L.geoJSON(json, {
maxZoom: level,
style: function (feature) {
return {
color: that.defaultColor
}
}
})
.on('mouseover', function (e) {
let pick = that.moveSelected;
if (pick.feature) {
pick.feature.setStyle({
color: pick.originalColor
});
pick.feature = undefined;
pick.originalColor = undefined;
}
if (that.openPolygon && e.sourceTarget) {
pick.feature = e.sourceTarget;
pick.originalColor = e.sourceTarget.options.style.color;
pick.feature.color = pick.selectedColor;
pick.feature.setStyle({
color: pick.selectedColor
});
}
})
.on('mouseout', function (e) {
let pick = that.moveSelected;
if (pick.feature) {
pick.feature.setStyle({
color: pick.originalColor
});
pick.feature = undefined;
pick.originalColor = undefined;
}
})
.on('dblclick', function (e) {
if (that.isDbClick != undefined && that.isDbClick == false) {
return;
}
that.dblclickTime = new Date().getTime();
if (that.openPolygon == false) {
return;
}
let coordinates = e.sourceTarget.feature.geometry.coordinates[0];
if (that.tempNodes && that.tempNodes.length > 0) {
that.removePolygon()
}
for (let i=0;i<coordinates.length;i++) {
that.addPoint(L.latLng([coordinates[i][1], coordinates[i][0]]))
}
that.closePolygon()
})
.addTo(map).setZIndex(2);
})
}
map.doubleClickZoom.disable();
map.on("dblclick", (e) => {
if (that.isDbClick != undefined && that.isDbClick == false) {
return;
}
that.dblclickTime = new Date().getTime();
that.$emit('updateCenter', [e.latlng.lat, e.latlng.lng])
that.setCenterPos(e.latlng);
});
} else {
if (that.marker != null) {
that.map.removeLayer(that.marker);
that.marker = null
}
while (that.polygon && that.polygon.length > 0) {
that.map.removeLayer(that.polygon[that.polygon.length - 1])
that.polygon.pop()
}
}
if (center && center != '') {
that.setCenterPos(center);
that.map.panTo(center);
}
if (boundaryCoordinate) {
let polygons = boundaryCoordinate;
polygons.forEach(coordinate => {
let polygon = L.polygon(coordinate, {
color: 'green',
fillColor: '#f03',
fillOpacity: 0.3
}).addTo(that.map);
that.polygon.push(polygon)
})
}
})
},
startPolygon() {
this.map.removeLayer(this.tempLines)
this.tempLines = new L.polyline([])
this.tempNodes.forEach(node => {
this.map.removeLayer(node)
})
this.tempNodes = [];
this.tempPoints = []
this.closed = false;
this.map.on('click', (e) => {
let that = this;
if (that.openPolygon == false) {
return;
}
setTimeout(function () {
let pre = that.dblclickTime;
if (pre == undefined || new Date().getTime() - pre > 220) {
that.addPoint(e.latlng)
}
}, 220)
});
this.openPolygon = true;
},
removePolygon() {
if (this.tempNodes.length > 0) {
this.map.removeLayer(this.tempLines)
this.tempLines = new L.polyline([])
this.tempNodes.forEach(node => {
this.map.removeLayer(node)
})
this.tempNodes = [];
this.tempPoints = []
this.closed = false;
} else {
this.map.off('click');
this.openPolygon = false;
if (this.polygon.length > 0) {
this.map.removeLayer(this.polygon[this.polygon.length - 1])
this.polygon.pop()
this.updatePolygon();
}
}
this.closed = false;
this.$emit('removePolygon');
},
closePolygon() {
this.closed = true;
this.addPoint();
this.openPolygon = false;
},
addPoint(latlng) {
if (this.closed==false) {
this.tempPoints.push([latlng.lat, latlng.lng]);
this.tempLines.addLatLng(latlng);
this.map.addLayer(this.tempLines);
const node = L.circle(latlng, 0.5, {
color: "#ff0000",
fillColor: "ff0000",
fillOpacity: 1,
});
this.tempNodes.push(node);
this.map.addLayer(node);
}
if (this.closed==true) {
let polygon = L.polygon(this.tempPoints, {
color: "green",
fillColor: "#f03",
fillOpacity: 0.5,
}).addTo(this.map);
this.polygon.push(polygon);
this.map.off("click");
this.removePolygon();
this.updatePolygon();
}
},
setCenterPos(latlng) {
if (this.marker != null) {
this.map.removeLayer(this.marker);
this.marker = null;
}
let marker = L.marker(latlng);
marker.addTo(this.map);
this.marker = marker;
},
panTo(center) {
if (center) {
this.map.panTo(center);
}
},
toVillage() {
if (this.center) {
this.map.panTo(this.center);
}
},
handlerSelect(e) {
let latlon = [e.lonlat.split(' ')[1], e.lonlat.split(' ')[0]];
this.map.panTo(latlon);
if (this.marker != null) {
this.map.removeLayer(this.marker);
this.marker = null;
}
let marker = L.marker({
lat: latlon[0],
lng: latlon[1]
});
marker.addTo(this.map);
this.marker = marker;
this.$emit('updateCenter', [e.lonlat.split(' ')[1], e.lonlat.split(' ')[0]])
},
handlerSelectAddress(e) {
this.$emit('updateAddress', e)
},
updatePolygon() {
let coordinateWgs = [];
this.polygon.forEach(polygon => {
if (polygon.getLatLngs() != null && polygon.getLatLngs().length > 0) {
let coordinates = []
polygon.getLatLngs()[0].forEach(item => {
coordinates.push([item.lat, item.lng])
})
coordinateWgs.push(coordinates);
}
})
this.coordinateWgs = coordinateWgs;
this.$emit('updatePolygon', coordinateWgs)
} ,
addMarker(latlng, iconUrl, tooltip, data, highlight) {
let icon = undefined;
if (iconUrl && iconUrl != '') {
icon = L.icon({
iconUrl: iconUrl,
iconSize: [32, 32],
iconAnchor: [32, 16],
});
}
let latlon = [latlng.split(',')[1], latlng.split(',')[0]];
let marker = icon ? L.marker(latlon, {
icon: icon
}) : L.marker(latlon);
marker.addTo(this.map);
let that = this;
marker.addEventListener('click', () => {
that.$emit('markerClick', data)
})
if (highlight) {
if (true == highlight.always) {
marker.unbindTooltip();
marker.bindTooltip(highlight.content, {
permanent: true,
direction: 'top',
offset: [-16, -16],
className: 'highlightMarker'
})
} else {
marker.unbindTooltip();
marker.bindTooltip(tooltip, {
permanent: true,
direction: 'top',
offset: [-16, -16],
className: 'marker-'+highlight.type
})
marker.addEventListener("mouseover", (e) => {
marker.unbindTooltip();
marker.bindTooltip(highlight.content, {
permanent: true,
direction: 'top',
offset: [-16, -16],
className: 'highlightMarker-'+highlight.type
})
})
marker.addEventListener("mouseout", (e) => {
marker.unbindTooltip();
marker.bindTooltip(tooltip, {
permanent: true,
direction: 'top',
offset: [-16, -16],
className: 'marker-'+highlight.type
})
})
}
} else {
marker.bindTooltip(tooltip, {
permanent: true,
direction: 'top',
offset: [-16, -16],
})
}
this.markers.push(marker);
},
clearMarkers() {
if (this.markers != null) {
for (let i=0;i<this.markers.length;i++) {
this.map.removeLayer(this.markers[i]);
}
this.markers = [];
}
},
}
}
</script>
<style lang="scss">
.marker-plain {
color: #606266;
background: #fff;
border-color: #dcdfe6;
}
.marker-primary {
color: #409eff;
background: #ecf5ff;
border-color: #b3d8ff;
}
.marker-success {
color: #67c23a;
background: #f0f9eb;
border-color: #c2e7b0;
}
.marker-info {
color: #909399;
background: #f4f4f5;
border-color: #d3d4d6;
}
.marker-warning {
color: #e6a23c;
background: #fdf6ec;
border-color: #f5dab1;
}
.marker-danger {
color: #f56c6c;
background: #fef0f0;
border-color: #fbc4c4;
}
.highlightMarker-plain {
font-size: 16px;
padding: 9px 18px;
line-height: 26px;
color: #606266;
background: #fff;
border-color: #dcdfe6;
}
.highlightMarker-primary {
font-size: 16px;
padding: 9px 18px;
line-height: 26px;
color: #409eff;
background: #ecf5ff;
border-color: #b3d8ff;
}
.highlightMarker-success {
font-size: 16px;
padding: 9px 18px;
line-height: 26px;
color: #67c23a;
background: #f0f9eb;
border-color: #c2e7b0;
}
.highlightMarker-info {
font-size: 16px;
padding: 9px 18px;
line-height: 26px;
color: #909399;
background: #f4f4f5;
border-color: #d3d4d6;
}
.highlightMarker-warning {
font-size: 16px;
padding: 9px 18px;
line-height: 26px;
color: #e6a23c;
background: #fdf6ec;
border-color: #f5dab1;
}
.highlightMarker-danger {
font-size: 16px;
padding: 9px 18px;
line-height: 26px;
color: #f56c6c;
background: #fef0f0;
border-color: #fbc4c4;
}
</style>
3- SearchComponent.vue
<template>
<div>
<el-autocomplete style="width: 320px;" size="small" placeholder="搜地名" v-model="address" :fetch-suggestions="search" @select="changePos" clearable></el-autocomplete>
</div>
</template>
<script>
export default {
data() {
return {
address: '',
pois: []
}
},
methods: {
search(address, cb) {
if (address && address != '') {
this.pois = [];
this.$http({
url: "patrol/map-search?address="+address,
method: "get",
}).then(res => {
this.pois = res.data;
let result = []
for(let i=0;i<this.pois.length;i++) {
result.push({
value: this.pois[i].address+'-'+this.pois[i].name,
})
}
cb(result)
})
} else {
cb([])
}
},
changePos(e) {
for(let i=0;i<this.pois.length;i++) {
if (e.value==this.pois[i].address+'-'+this.pois[i].name) {
this.$emit("select", this.pois[i])
this.$emit("selectAddress", e.value)
}
}
}
}
}
</script>
<style scoped>
</style>
4 - vue 页面
<template>
<div class=''>
<el-form ref="rules" :model="form" label-width="150px" :rules="rules">
<el-row :gutter="60">
<el-col :span="7">
<el-form-item label="坐标" prop="landPoint">
<el-input disabled v-model="form.landPoint" placeholder="双击地图或搜索"></el-input>
</el-form-item>
</el-col>
<el-col :span="15">
<el-form-item label="范围">
<el-input disabled type="textarea" placeholder="自动生成" clearable v-model="form.boundaryCoordinate"
:autosize="{ minRows: 1, maxRows: 4 }" />
</el-form-item>
</el-col>
</el-row>
<div class="_map">
<TdtMap ref="tdtMap" :isSearch="true" :isPolygon="true" v-on:updateCenter="updateCenter"
v-on:updatePolygon="updatePolygon" style="border: solid 1px #EEEEEE;border-radius: 5px;"> </TdtMap>
</div>
</el-form>
</div>
</template>
methods: {
updateCenter(center) {
this.form.landPoint = center[1] + ',' + center[0];
},
updatePolygon(boundaryCoordinate) {
let _boundaryCoordinate = '';
let temp = [];
boundaryCoordinate.forEach(polygon => {
let coordinates = []
polygon.forEach(item => {
coordinates.push(item[1] + ',' + item[0])
})
temp.push(coordinates.join('|'))
})
_boundaryCoordinate = temp.join('&&')
this.form.boundaryCoordinate = _boundaryCoordinate;
},
mapInit() {
let center = undefined;
let boundaryCoordinate = undefined;
if (this.form.landPoint && this.form.landPoint != '') {
center = this.form.landPoint.split(",").reverse();
}
if (this.form.boundaryCoordinate && this.form.boundaryCoordinate != '') {
boundaryCoordinate = []
let polygons = this.form.boundaryCoordinate.split('&&');
polygons.forEach(coordinate => {
let zbs = coordinate.split('|')
let polygonPath = [];
zbs.forEach(item => {
polygonPath.push([item.split(',')[1], item.split(',')[0]])
})
boundaryCoordinate.push(polygonPath)
})
}
this.$refs.tdtMap.mapInit(center, boundaryCoordinate)
}
},
mounted() {
this.form = this.data;
if (!this.id) {
this.$refs.tdtMap.mapInit()
}
},