| | |
| | | <template> |
| | | <div class="map-index"> |
| | | |
| | | <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> |
| | | export default { |
| | | 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 { |
| | | width: 1170px; |
| | | height: 396px; |
| | | border-radius: 15px; |
| | | background-color: skyblue |
| | | } |
| | | #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> |