<template>
|
<div id="map-index">
|
<div class="control">
|
<div class="location icon iconfont" @click="location"></div>
|
<div class="zoom-in icon iconfont" @click="zoomIn"></div>
|
<div class="zoom-out icon iconfont" @click="zoomOut"></div>
|
</div>
|
<div class="range icon iconfont" @click="drawPolygon"></div>
|
<el-input v-model="nodeId" placeholder="请输入内容"></el-input>
|
<div class="save" v-if="showBtn" @click="savePoly">保存</div>
|
<div class="cancel" v-if="showBtn" @click="resetMap">取消</div>
|
</div>
|
</template>
|
|
<script>
|
import "ol/ol.css";
|
import Feature from "ol/Feature";
|
import Point from "ol/geom/Point";
|
import VectorSource from "ol/source/Vector";
|
import { Icon, Style, Fill, Stroke } from "ol/style";
|
import { transform } from "ol/proj";
|
import { Map, View } from "ol";
|
import TileLayer from "ol/layer/Tile";
|
import { Vector as VectorLayer } from "ol/layer";
|
import OSM from "ol/source/OSM";
|
import Draw from "ol/interaction/Draw";
|
import { Modify, Snap } from "ol/interaction";
|
import Polygon from "ol/geom/Polygon";
|
|
let myMap = {};
|
let myVectorSource = {};
|
let baseLayer = new TileLayer({
|
source: new OSM({
|
// url:'http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=8',
|
url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7",
|
crossOrigin: "anonymous",
|
// url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
|
}),
|
});
|
let myDraw = {};
|
let myModify = {};
|
|
export default {
|
data() {
|
return {
|
showBtn: false,
|
nodeArr: [
|
{ data: [116.06157, 39.66157], id: 1, color: "绿" },
|
{ data: [116.06247, 39.66247], id: 2, color: "绿" },
|
{ data: [116.06337, 39.66337], id: 3, color: "绿" },
|
{ data: [116.06467, 39.66437], id: 4, color: "绿" },
|
{ data: [116.06517, 39.66517], id: 5, color: "红" },
|
{ data: [116.06627, 39.66627], id: 6, color: "红" },
|
{ data: [116.06787, 39.66787], id: 7, color: "红" },
|
{ data: [116.06897, 39.66897], id: 8, color: "红" },
|
],
|
nodeId: "",
|
iconArr: [],
|
rangeArr: [],
|
zoom: 15,
|
center: [116.06667, 39.66667],
|
polygonArr: [
|
{
|
data: [
|
[12919660.904416857, 4817401.4907109635],
|
[12921041.54824026, 4817277.28054],
|
[12920195.963614853, 4816775.662541878],
|
[12919493.698417485, 4816785.2171704145],
|
],
|
id: "1",
|
},
|
],
|
polyFeature: [],
|
drawStore: [],
|
modifyStore: [],
|
};
|
},
|
mounted() {
|
this.initMap();
|
},
|
methods: {
|
initMap() {
|
this.initPolygonArr();
|
const vectorSource = new VectorSource({
|
features: this.polyFeature,
|
});
|
/* if(this.polygonArr.length>0){
|
this.initPolygonArr()
|
console.log(this.polyFeature);
|
vectorSource.addFeature(this.polyFeature[0])
|
} */
|
myVectorSource = vectorSource;
|
this.initAllNode();
|
|
const vectorLayer = this.initLayer(vectorSource);
|
|
const map = this.initBottomMap(vectorLayer);
|
|
myMap = map;
|
/* map.getView().on('change:resolution', ()=> {
|
this.iconArr.forEach(item=>{
|
let style = item.getStyle()
|
console.log(this.zoom);
|
style.getImage().setScale(this.zoom/15)
|
item.setStyle(style)
|
console.log(item);
|
})
|
}) */
|
},
|
initNode([x, y], color) {
|
const iconFeature = new Feature({
|
geometry: new Point(transform([x, y], "EPSG:4326", "EPSG:3857")),
|
});
|
|
const iconStyle = new Style({
|
image: new Icon({
|
size: [32, 32],
|
src: `/images/map/安全帽-${color}.png`,
|
}),
|
zIndex: 1,
|
});
|
|
iconFeature.setStyle(iconStyle);
|
this.iconArr.push(iconFeature);
|
return iconFeature;
|
},
|
initAllNode() {
|
this.nodeArr.forEach((item) => {
|
const node = this.initNode(item.data, item.color);
|
node.set("id", item.id);
|
myVectorSource.addFeature(node);
|
});
|
},
|
initPolygonArr() {
|
this.polyFeature = [];
|
this.polygonArr.forEach((item) => {
|
const feature = new Feature({ geometry: new Polygon([item.data]) });
|
feature.id = item.id;
|
this.polyFeature.push(feature);
|
});
|
},
|
initLayer(source) {
|
return new VectorLayer({
|
source: source,
|
style: new Style({
|
fill: new Fill({
|
color: "rgba(255, 255, 255, 0.4)",
|
}),
|
stroke: new Stroke({
|
color: "#F54336",
|
width: 2,
|
}),
|
}),
|
});
|
},
|
initBottomMap(vectorLayer) {
|
return new Map({
|
target: "map-index",
|
layers: [baseLayer, vectorLayer],
|
view: new View({
|
center: transform(this.center, "EPSG:4326", "EPSG:3857"),
|
zoom: this.zoom,
|
}),
|
});
|
},
|
zoomIn() {
|
const view = myMap.getView();
|
this.zoom++;
|
view.setZoom(this.zoom);
|
},
|
zoomOut() {
|
const view = myMap.getView();
|
this.zoom--;
|
view.setZoom(this.zoom);
|
},
|
location() {
|
const view = myMap.getView();
|
view.setZoom(this.zoom);
|
view.setCenter(
|
transform([116.06667, 39.66667], "EPSG:4326", "EPSG:3857")
|
);
|
},
|
drawPolygon() {
|
this.showBtn = true;
|
const draw = new Draw({
|
source: myVectorSource,
|
type: "Polygon",
|
});
|
myDraw = draw;
|
draw.on("drawend", (event) => {
|
let id =
|
this.drawStore.length > 0
|
? +this.drawStore[this.drawStore.length - 1].id + 1
|
: +this.polygonArr[this.polygonArr.length - 1].id + 1;
|
event.feature.id = id;
|
this.drawStore.push({
|
id,
|
data: event.feature.getGeometry().getCoordinates()[0],
|
});
|
});
|
|
const modify = new Modify({ source: myVectorSource });
|
modify.addEventListener("modifyend", (event) => {
|
console.log(event.features);
|
const id = event.features.array_[0].id;
|
const data = event.features.array_[0].getGeometry().getCoordinates()[0];
|
this.modifyStore.push({ id, data });
|
});
|
myModify = modify;
|
myMap.addInteraction(modify);
|
myMap.addInteraction(draw);
|
},
|
resetMap() {
|
this.initPolygonArr();
|
console.log(this.polyFeature);
|
const vectorSource = new VectorSource({
|
features: this.polyFeature,
|
});
|
/* if(this.polygonArr.length>0){
|
this.initPolygonArr()
|
console.log(this.polyFeature);
|
vectorSource.addFeature(this.polyFeature[0])
|
} */
|
myVectorSource = vectorSource;
|
this.initAllNode();
|
|
const vectorLayer = this.initLayer(vectorSource);
|
myMap.setLayers([baseLayer, vectorLayer]);
|
myMap.removeInteraction(myDraw);
|
myMap.removeInteraction(myModify);
|
this.showBtn = false;
|
this.drawStore = [];
|
this.modifyStore = [];
|
},
|
savePoly() {
|
myMap.removeInteraction(myDraw);
|
myMap.removeInteraction(myModify);
|
this.showBtn = false;
|
if (this.drawStore.length) {
|
this.polygonArr = [...this.polygonArr, ...this.drawStore];
|
this.drawStore = [];
|
}
|
if (this.modifyStore.length) {
|
this.modifyStore.forEach((item) => {
|
this.polygonArr.forEach((item2) => {
|
if (item.id == item2.id) {
|
item2.data = item.data;
|
}
|
});
|
});
|
this.modifyStore = [];
|
}
|
},
|
},
|
watch: {
|
nodeId: {
|
handler(val) {
|
const arr = this.nodeArr.filter((item) => item.id == val);
|
if (this.rangeArr.length > 0) {
|
this.rangeArr.forEach((item) => {
|
myVectorSource.removeFeature(item);
|
});
|
this.rangeArr = [];
|
}
|
|
if (arr.length > 0) {
|
arr.forEach((item) => {
|
const rangeFeature = new Feature({
|
geometry: new Point(
|
transform(item.data, "EPSG:4326", "EPSG:3857")
|
),
|
name: "Null Island",
|
population: 4000,
|
rainfall: 500,
|
});
|
|
const iconStyle = new Style({
|
image: new Icon({
|
size: [64, 64],
|
src: `/images/map/范围-${item.color}.png`,
|
}),
|
});
|
|
rangeFeature.setStyle(iconStyle);
|
myVectorSource.addFeature(rangeFeature);
|
this.rangeArr.push(rangeFeature);
|
});
|
}
|
},
|
},
|
},
|
};
|
</script>
|
|
<style scoped lang="scss">
|
#map-index {
|
position: relative;
|
margin: 20px 0;
|
width: 1170px;
|
height: 396px;
|
border-radius: 15px;
|
.control {
|
position: absolute;
|
display: flex;
|
flex-direction: column;
|
z-index: 1;
|
left: 25px;
|
bottom: 25px;
|
width: 30px;
|
height: 91px;
|
background: #ffffff;
|
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.25);
|
border-radius: 8px;
|
.location,
|
.zoom-in,
|
.zoom-out {
|
line-height: 30px;
|
font-size: 18px;
|
flex: 1;
|
cursor: pointer;
|
}
|
.location {
|
background: #11aa66;
|
border-radius: 8px 8px 0 0;
|
color: #fff;
|
}
|
}
|
.el-input {
|
position: absolute;
|
z-index: 1;
|
top: 15px;
|
left: 15px;
|
width: 205px;
|
height: 35px;
|
::v-deep input {
|
width: 100%;
|
height: 100%;
|
|
&:focus {
|
border-color: #11aa66 !important;
|
}
|
}
|
}
|
.range {
|
position: absolute;
|
left: 25px;
|
bottom: 126px;
|
width: 30px;
|
height: 30px;
|
background: #11aa66;
|
color: #fff;
|
border-radius: 8px;
|
cursor: pointer;
|
z-index: 1;
|
line-height: 30px;
|
}
|
.save {
|
position: absolute;
|
z-index: 3;
|
top: 15px;
|
right: 113px;
|
width: 87px;
|
height: 35px;
|
background: #11aa66;
|
border: 1px solid #11aa66;
|
border-radius: 8px;
|
color: #fff;
|
font-size: 12px;
|
line-height: 36px;
|
cursor: pointer;
|
}
|
|
.cancel {
|
position: absolute;
|
z-index: 3;
|
top: 15px;
|
right: 20px;
|
width: 87px;
|
height: 35px;
|
background: #fff;
|
border: 1px solid #11aa66;
|
border-radius: 8px;
|
color: #4f4f4f;
|
font-size: 12px;
|
line-height: 36px;
|
cursor: pointer;
|
}
|
}
|
</style>
|
|
<style>
|
.ol-zoom {
|
display: none !important;
|
}
|
</style>
|