| | |
| | | <!-- |
| | | * @Description: 绘制图形统计圈内点数 |
| | | * @Author: Dragon |
| | | * @Date: 2020-12-21 13:19:47 |
| | | * @LastEditTime: 2020-12-21 15:03:27 |
| | | * @LastEditors: Dragon |
| | | * @Descripttion: |
| | | * @version: |
| | | * @Author: song |
| | | * @Date: 2021-04-08 15:14:57 |
| | | * @LastEditors: song |
| | | * @LastEditTime: 2021-04-24 11:59:43 |
| | | --> |
| | | |
| | | <template> |
| | | <div> |
| | | <div class="query-wrap"> |
| | | <el-button type="primary" @click="drawStart('Polygon')"> |
| | | {{ isDraw ? "绘制区域查询人数" : "重新绘制" }} |
| | | </el-button> |
| | | <div id="map" style="height: 100%"> |
| | | <div class="controlMap"> |
| | | <el-button-group> |
| | | <el-button |
| | | type="primary" |
| | | icon="el-icon-edit" |
| | | @click="getTypeSelected" |
| | | :disabled="beginDraw" |
| | | >{{ butTitle }}</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | :disabled="!beginDraw" |
| | | @click="stopDraw" |
| | | icon="el-icon-delete" |
| | | >取消</el-button |
| | | > |
| | | <!-- <el-button type="primary" icon="el-icon-share"></el-button> |
| | | <el-button type="primary" icon="el-icon-delete"></el-button> --> |
| | | </el-button-group> |
| | | </div> |
| | | <div id="map"></div> |
| | | <tip v-show="showTip" :title="tipTitle" :position="position"></tip> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import "ol/ol.css"; |
| | | import OlView from "ol/View.js"; |
| | | import XYZ from "ol/source/XYZ"; |
| | | import OlLayerTile from "ol/layer/Tile.js"; |
| | | import OlMap from "ol/Map.js"; |
| | | import tip from "./tip.vue"; |
| | | import { |
| | | // eslint-disable-next-line no-unused-vars |
| | | defaults as OlControlDefaults, |
| | | defaults, |
| | | // 全屏控件 |
| | | FullScreen, |
| | | // 比例尺控件 |
| | | ScaleLine, |
| | | // 缩放滚动条控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | ZoomSlider, |
| | | // 鼠标位置控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | MousePosition, |
| | | // -地图属性控件 |
| | | Attribution, |
| | | // 鹰眼控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | OverviewMap, |
| | | // 缩放到范围控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | ZoomToExtent, |
| | | Rotate, |
| | | } from "ol/control.js"; |
| | | import "ol/ol.css"; |
| | | import { Map, View, Feature } from "ol"; |
| | | import { Image as ImageLayer, Vector as VectorLayer } from "ol/layer"; |
| | |
| | | import Draw from "ol/interaction/Draw"; |
| | | import { Point } from "ol/geom"; |
| | | import { Icon, Style, Text, Fill, Stroke } from "ol/style"; |
| | | |
| | | import staticMap from "@/assets/img/car.png"; |
| | | |
| | | |
| | | import { Vector } from "ol/source"; |
| | | // import Draw from "./Draw"; |
| | | import LineString from "ol/geom/LineString.js"; |
| | | import img from "@/assets/img/car.png"; |
| | | |
| | | |
| | | export default { |
| | | name: "Map", |
| | | components: { |
| | | tip, |
| | | }, |
| | | data() { |
| | | return { |
| | | map: null, // 地图 |
| | | imgx: 0, // 当前地图宽 |
| | | imgy: 0, // 当前地图高 |
| | | isDraw: true, // 是否绘制 |
| | | draw: null, |
| | | source: null, |
| | | vector: null, |
| | | styles: [ |
| | | new Style({ |
| | | stroke: new Stroke({ |
| | | color: "rgba(255,0,0,0.6)", |
| | | width: 2, |
| | | }), |
| | | fill: new Fill({ |
| | | color: "rgba(255,0,0,0.3)", |
| | | }), |
| | | }), |
| | | ], |
| | | peopleLineAddlayer: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | //多边形Layer |
| | | polygonlayer: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | vectorSource: new VectorSource(), |
| | | features: [], |
| | | feature: null, |
| | | // 存储新增点,线,面,数据的地方 |
| | | persons: [], |
| | | polygon: [], |
| | | polygonPersons: [], |
| | | features: [], |
| | | feature: null, |
| | | vectorSource: new VectorSource(), |
| | | timer: null, |
| | | // polygonData: [], |
| | | // polygonFlag: false, |
| | | // editToolbar: null, |
| | | // addPolygonEntitys: null, |
| | | |
| | | typeSelected: "Polygon", |
| | | drawLayer: null, |
| | | draw: null, |
| | | drawSource:null, |
| | | coordinates: [], |
| | | coordinatesStr: "", |
| | | beginDraw: false, |
| | | butTitle: "开始绘画", |
| | | view: "", |
| | | isDraw: true, // 是否绘制 |
| | | showTip: false, |
| | | tipTitle: "", |
| | | position: { |
| | | w: 200, |
| | | h: 10, |
| | | }, |
| | | }; |
| | | }, |
| | | |
| | | mounted() { |
| | | const ol2d = new OlMap({ |
| | | layers: [ |
| | | new OlLayerTile({ |
| | | zIndex: 4, |
| | | title: "影像", |
| | | source: new XYZ({ |
| | | url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划 |
| | | }), |
| | | }), |
| | | ], |
| | | |
| | | // 注意地图控件的写法 |
| | | controls: defaults().extend([ |
| | | // new FullScreen(), |
| | | // new ScaleLine(), |
| | | // new MousePosition(), |
| | | // new Rotate(), |
| | | // new Attribution() |
| | | ]), |
| | | target: "map", |
| | | view: new OlView({ |
| | | center: [0, 0], |
| | | zoom: 2, |
| | | projection: "EPSG:4326", |
| | | }), |
| | | }); |
| | | window.ol2d = ol2d; |
| | | |
| | | var view = ol2d.getView(); |
| | | |
| | | // view.setCenter([115.85883507433789, 28.708432053474827]) |
| | | view.setCenter([115.9032747077233, 28.67433116990186]); |
| | | |
| | | //设置放大层级 |
| | | view.setZoom(13); |
| | | this.view = view; |
| | | |
| | | // const drawSource = new VectorSource(); |
| | | |
| | | // const drawLayer = new VectorLayer({ |
| | | |
| | | // source: drawSource |
| | | |
| | | // }); |
| | | |
| | | // this.drawSource = drawSource; |
| | | |
| | | // ol2d.addLayer(drawLayer); |
| | | |
| | | ol2d.addLayer(this.peopleLineAddlayer); |
| | | ol2d.addLayer(this.polygonlayer); |
| | | |
| | | //监听鼠标位置 |
| | | var that = this; |
| | | // |
| | | that.addNewLine(); |
| | | var obj = { |
| | | fenceId: '12', |
| | | name: '围栏3', |
| | | center: '', |
| | | radius: '', |
| | | type: 'polyline', |
| | | points: '113.960623,22.546082;113.958197,22.544029;113.956526,22.543245;113.953562,22.544563' |
| | | } |
| | | this.showFence(obj); |
| | | }, |
| | | watch: { |
| | | persons(val) { |
| | |
| | | }, |
| | | }, |
| | | methods: { |
| | | // 初始化地图 |
| | | initMap() { |
| | | let extent = [0, 0, this.imgx, this.imgy]; |
| | | let projection = new Projection({ |
| | | extent: extent, |
| | | }); |
| | | let $this = this; |
| | | // 默认地图 |
| | | let mapLayer = new ImageLayer({ |
| | | source: new ImageStatic({ |
| | | url: staticMap, |
| | | projection: projection, |
| | | imageExtent: extent, |
| | | }), |
| | | }); |
| | | |
| | | // 绘制点 |
| | | let featureLayer = new VectorLayer({ |
| | | source: this.vectorSource, |
| | | }); |
| | | |
| | | this.map = new Map({ |
| | | target: "map", |
| | | layers: [ |
| | | mapLayer, // 展示地图层 |
| | | featureLayer, // 点 |
| | | ], |
| | | view: new View({ |
| | | projection: projection, |
| | | center: getCenter(extent), |
| | | zoom: 2, |
| | | maxZoom: 18, |
| | | }), |
| | | }); |
| | | |
| | | this.source = new VectorSource({ wrapX: false }); |
| | | this.vector = new VectorLayer({ |
| | | source: this.source, |
| | | style: this.styles, |
| | | }); |
| | | this.map.addLayer(this.vector); |
| | | goTudefault(x, y) { |
| | | this.view.setCenter([x, y]); |
| | | this.view.setZoom(14.5); |
| | | }, |
| | | |
| | | // 点 |
| | | setFeature() { |
| | | let that = this; |
| | |
| | | }); |
| | | that.vectorSource.addFeatures(that.features); |
| | | }, |
| | | |
| | | // 开始绘制多边形 |
| | | addEntitys(item, icon, scale, name, type) { |
| | | const iconFeature = new Feature({ |
| | | geometry: new Point([Number(item.LGTD), Number(item.LTTD)]), |
| | | name: name, |
| | | attributes: item, |
| | | }); |
| | | |
| | | const iconStyle = new Style({ |
| | | image: new Icon({ |
| | | scale: scale, |
| | | opacity: 1, |
| | | src: icon, |
| | | // src: require('../../assets/Mark.png') |
| | | }), |
| | | }); |
| | | |
| | | iconFeature.setStyle(iconStyle); |
| | | |
| | | this[type].getSource().addFeature(iconFeature); |
| | | }, |
| | | |
| | | addLines(ringId) { |
| | | var that = this; |
| | | if (ringId != null && ringId != "") { |
| | | $.ajax({ |
| | | url: "api/routeIn/routein/selectList", |
| | | type: "post", |
| | | data: { |
| | | id: ringId, |
| | | }, |
| | | dataType: "JSON", |
| | | success: function (data) { |
| | | that.peopleLineAddlayer.getSource().clear(); |
| | | var entityData = ""; |
| | | var entityArr = []; |
| | | entityData = data.data[0].routeInfo.match(/\(([^)]*)\)/); |
| | | |
| | | // 此时result=["(dsfasjfj3124123)", "dsfasjfj3124123"]; |
| | | if (entityData && entityData != "") { |
| | | entityData = entityData[1].split(","); |
| | | |
| | | for (var j = 0; j < entityData.length; j++) { |
| | | entityArr.push([ |
| | | Number(entityData[j].split(" ")[0]), |
| | | Number(entityData[j].split(" ")[1]), |
| | | ]); |
| | | } |
| | | } |
| | | |
| | | var lineCoords = entityArr; // 线里点的集合 |
| | | |
| | | var view = ol2d.getView(); |
| | | view.setCenter([ |
| | | lineCoords[Math.ceil(entityArr.length / 2)][0], |
| | | lineCoords[Math.ceil(entityArr.length / 2)][1], |
| | | ]); |
| | | view.setZoom(14.5); |
| | | |
| | | // 要素 |
| | | // var lineCoords = [[featureInfo.lineString[0][0],featureInfo.lineString[0][0]],[featureInfo.lineString(0),featureInfo.lineString(0)]]; |
| | | var feature_LineString = new Feature({ |
| | | geometry: new LineString(lineCoords), |
| | | }); |
| | | |
| | | feature_LineString.setStyle( |
| | | new Style({ |
| | | //填充色 |
| | | fill: new Fill({ |
| | | color: "rgba(255, 255, 255, 0.2)", |
| | | }), |
| | | //边线颜色 |
| | | stroke: new Stroke({ |
| | | color: "rgb(252, 94, 32)", |
| | | width: 5, |
| | | }), |
| | | }) |
| | | ); |
| | | that.peopleLineAddlayer.getSource().addFeature(feature_LineString); |
| | | that.butTitle = "修改绘画"; |
| | | }, |
| | | error: function (data) { |
| | | // 请求失败函数 |
| | | console.log(data); |
| | | }, |
| | | }); |
| | | } |
| | | }, |
| | | addNewLine() { |
| | | this.map = ol2d; |
| | | |
| | | // 添加一个绘制的线使用的layer |
| | | this.drawLayer = new VectorLayer({ |
| | | //layer所对应的source |
| | | source: new Vector(), |
| | | }); |
| | | //把layer加入到地图中 |
| | | this.map.addLayer(this.drawLayer); |
| | | }, |
| | | //转换坐标点(多) |
| | | transPoints(points) { |
| | | let arr = points.split(';'); |
| | | let point = []; |
| | | arr.forEach(item => { |
| | | let newPoint = item.split(','); |
| | | point.push(newPoint) |
| | | }) |
| | | let _points = point.map(item => { |
| | | item = [parseFloat(item[0]), parseFloat(item[1])]; |
| | | item = ol.proj.transform(item, 'EPSG:4326', 'EPSG:3857'); |
| | | return item; |
| | | }) |
| | | return _points; |
| | | }, |
| | | //回显围栏 |
| | | showFence(obj) { |
| | | let { |
| | | fenceId, |
| | | name, |
| | | type, |
| | | center, |
| | | radius, |
| | | points |
| | | } = obj; |
| | | if (type == 'polygon') { |
| | | this.showPolygon(fenceId, points, name) |
| | | } |
| | | }, |
| | | /** |
| | | * |
| | | * @param {*} fenceId 围栏id |
| | | * @param {*} points 多边形坐标点 |
| | | * @param {*} name 围栏名 |
| | | */ |
| | | showPolygon(fenceId, points, name) { |
| | | let _points = this.transPoints(points) |
| | | _points = [_points] |
| | | //多边形的数据格式是[[[lng,lat],[lng,lat]……]]外围两个中括号 |
| | | var polygonFeature = new ol.Feature({ //路线 |
| | | geometry: new ol.geom.Polygon(_points) |
| | | |
| | | }); |
| | | debugger; |
| | | polygonFeature.setId(fenceId) |
| | | this.source.addFeature(polygonFeature); |
| | | console.log(this.source.getFeatures()) |
| | | }, |
| | | //开始绘制 |
| | | getTypeSelected() { |
| | | this.beginDraw = true; |
| | | this.draw && this.map.removeInteraction(this.draw); |
| | | this.peopleLineAddlayer.getSource().clear(); |
| | | this.polygonlayer.getSource().clear(); |
| | | //再根据typeSelect的值绘制新的Interaction |
| | | // this.addInteraction(); |
| | | this.drawStart(); |
| | | }, |
| | | stopDraw() { |
| | | this.showTip = false; |
| | | this.draw && this.map.removeInteraction(this.draw); |
| | | this.beginDraw = false; |
| | | this.tipTitle = ""; |
| | | this.$store.commit("setRotesData", ""); //用vuex传最终数据 |
| | | }, |
| | | setTipPosition(x, y, n, m) { |
| | | this.position.w = x + n; |
| | | this.position.h = y + m; |
| | | }, |
| | | //绘制开始 |
| | | addInteraction() { |
| | | this.tipTitle = "单击左键或右键开始绘画"; |
| | | // $("#map") |
| | | // .off("mousemove") |
| | | // .mousemove(function (e) { |
| | | // if (!that.showTip) { |
| | | // that.showTip = true; |
| | | // } |
| | | // that.setTipPosition(e.offsetX, e.offsetY, 10, 10); |
| | | // }); |
| | | |
| | | this.coordinates = []; |
| | | let value = this.typeSelected, |
| | | that = this; |
| | | |
| | | if (value !== "None") { |
| | | this.draw = new Draw({ |
| | | source: this.drawLayer.getSource(), |
| | | type: this.typeSelected, |
| | | style: new Style({ |
| | | stroke: new Stroke({ |
| | | color: "red", |
| | | width: 3, |
| | | }), |
| | | }), |
| | | coordinate: function (res) { |
| | | //画线中的点 |
| | | that.coordinates.push(res); |
| | | that.tipTitle = "可继续,或选择最终位置双击结束"; |
| | | }, |
| | | coordinateOver: function (res) { |
| | | // 结束绘画 处理数据 |
| | | // console.log(that.doData(that.coordinates)); |
| | | let d = that.doData(that.coordinates); |
| | | that.addLinesDraw(d); |
| | | // console.log(d); |
| | | // console.log(that.$store); |
| | | that.$store.commit("setRotesData", d); //用vuex传最终数据 |
| | | // that.coordinatesStr = that.doData(that.coordinates); |
| | | }, |
| | | }); |
| | | this.map.addInteraction(this.draw); |
| | | } |
| | | }, |
| | | // 开始绘制多边形 |
| | | drawStart(type) { |
| | | type = 'Polygon'; |
| | | let that = this; |
| | | var draw; |
| | | if (this.isDraw) { |
| | | this.isDraw = false; |
| | | this.draw = new Draw({ |
| | | draw = new Draw({ |
| | | source: this.source, |
| | | type: type, |
| | | }); |
| | | this.map.addInteraction(this.draw); |
| | | this.draw.on("drawend", function (evt) { |
| | | draw.on("drawend", function (evt) { |
| | | that.drawingEnd(evt); |
| | | }); |
| | | } else { |
| | |
| | | that.polygon.push({ lng: item[0], lat: item[1] }); |
| | | }); |
| | | for (let i = 0; i < this.persons.length; i++) { |
| | | let boxFlag = this.isRegion(this.persons[i].x, this.persons[i].y, this.polygon); |
| | | if (boxFlag) { |
| | | this.polygonPersons.push(this.persons[i]); |
| | | } |
| | | this.polygonPersons.push(this.persons[i]); |
| | | } |
| | | this.$message({ |
| | | type: "success", |
| | | message: `区域内有${this.polygonPersons.length}人`, |
| | | }); |
| | | console.warn(this.polygonPersons, `区域内有${this.polygonPersons.length}人`); |
| | | this.map.removeInteraction(this.draw); |
| | | this.isDraw = false; |
| | | } |
| | | }, |
| | | |
| | | // 验证点是否在区域内 |
| | | isRegion(lon, lat, aPoints) { |
| | | let num = 0, |
| | | iCount; |
| | | let dLon1, dLon2, dLat1, dLat2, dLon; |
| | | if (aPoints.length < 3) return false; |
| | | iCount = aPoints.length; |
| | | for (let i = 0; i < iCount; i++) { |
| | | if (i == iCount - 1) { |
| | | dLon1 = aPoints[i].lng; |
| | | dLat1 = aPoints[i].lat; |
| | | dLon2 = aPoints[0].lng; |
| | | dLat2 = aPoints[0].lat; |
| | | } else { |
| | | dLon1 = aPoints[i].lng; |
| | | dLat1 = aPoints[i].lat; |
| | | dLon2 = aPoints[i + 1].lng; |
| | | dLat2 = aPoints[i + 1].lat; |
| | | } |
| | | if ((lat >= dLat1 && lat < dLat2) || (lat >= dLat2 && lat < dLat1)) { |
| | | if (Math.abs(dLat1 - dLat2) > 0) { |
| | | dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - lat)) / (dLat1 - dLat2); |
| | | if (dLon < lon) num++; |
| | | } |
| | | doData(val) { |
| | | // ` routeInfo: " |
| | | // LINESTRING( |
| | | // 115.875489096939 28.7179278611352 |
| | | // ,115.8794051221 28.7176267680684 |
| | | // ,115.879340749084 28.7143052776491 |
| | | // ,115.878879409134 28.7140324026424 |
| | | // ,115.875220876038 28.7150580325974 |
| | | // ,115.875489096939 28.7179466794231 |
| | | // ,115.875489096939 28.7179466794231 |
| | | // )" |
| | | // ` |
| | | let str = "LINESTRING("; |
| | | for (let k = 0; k < val.length; k++) { |
| | | str += `${val[k][0]} ${val[k][1]}`; |
| | | if (k != val.length - 1) { |
| | | str += ","; |
| | | } |
| | | } |
| | | if (num % 2 != 0) return true; |
| | | return false; |
| | | str += ")"; |
| | | // console.log(str, 111); |
| | | return str; |
| | | }, |
| | | }, |
| | | mounted() { |
| | | let img = new Image(); |
| | | img.src = staticMap; |
| | | let that = this; |
| | | img.onload = function (res) { |
| | | that.imgx = res.target.width; |
| | | that.imgy = res.target.height; |
| | | that.initMap(); |
| | | }; |
| | | }, |
| | | created() { |
| | | let that = this; |
| | | that.timer = setInterval(function () { |
| | | that.persons = [ |
| | | { id: 1, name: "点-1", x: 497.08, y: 187.88, z: 0 }, |
| | | { id: 2, name: "点-2", x: 725.32, y: 565.88, z: 0 }, |
| | | { id: 3, name: "点-3", x: 643.24, y: 503.96, z: 0 }, |
| | | ]; |
| | | }, 2000); |
| | | }, |
| | | beforeDestroy() { |
| | | clearInterval(this.timer); |
| | | addLinesDraw(val) { |
| | | var that = this; |
| | | that.peopleLineAddlayer.getSource().clear(); |
| | | that.polygonlayer.getSource().clear(); |
| | | var entityData = ""; |
| | | var entityArr = []; |
| | | entityData = val.match(/\(([^)]*)\)/); |
| | | |
| | | // 此时result=["(dsfasjfj3124123)", "dsfasjfj3124123"]; |
| | | if (entityData && entityData != "") { |
| | | entityData = entityData[1].split(","); |
| | | |
| | | for (var j = 0; j < entityData.length; j++) { |
| | | entityArr.push([ |
| | | Number(entityData[j].split(" ")[0]), |
| | | Number(entityData[j].split(" ")[1]), |
| | | ]); |
| | | } |
| | | } |
| | | |
| | | var lineCoords = entityArr; // 线里点的集合 |
| | | |
| | | var view = ol2d.getView(); |
| | | view.setCenter([ |
| | | lineCoords[Math.ceil(entityArr.length / 2)][0], |
| | | lineCoords[Math.ceil(entityArr.length / 2)][1], |
| | | ]); |
| | | view.setZoom(14.5); |
| | | |
| | | // 要素 |
| | | // var lineCoords = [[featureInfo.lineString[0][0],featureInfo.lineString[0][0]],[featureInfo.lineString(0),featureInfo.lineString(0)]]; |
| | | var feature_LineString = new Feature({ |
| | | geometry: new LineString(lineCoords), |
| | | }); |
| | | |
| | | feature_LineString.setStyle( |
| | | new Style({ |
| | | //填充色 |
| | | fill: new Fill({ |
| | | color: "rgba(255, 255, 255, 0.2)", |
| | | }), |
| | | //边线颜色 |
| | | stroke: new Stroke({ |
| | | color: "rgb(252, 94, 32)", |
| | | width: 5, |
| | | }), |
| | | }) |
| | | ); |
| | | that.peopleLineAddlayer.getSource().addFeature(feature_LineString); |
| | | that.polygonlayer.getSource().addFeature(feature_LineString); |
| | | if (that.draw != null) { |
| | | that.beginDraw = false; |
| | | that.butTitle = "重新绘画"; |
| | | that.draw.abortDrawing_(); |
| | | that.tipTitle = "已结束绘画,点击重新绘画清除上次内容并开始绘画"; |
| | | $("#map").unbind("mousemove"); |
| | | // setTimeout(() => { |
| | | this.tipTitle = ""; |
| | | this.showTip = false; |
| | | } |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | <style scoped lang="scss"> |
| | | #map { |
| | | width: 100%; |
| | | height: calc(100vh - 50px); |
| | | position: relative; |
| | | .controlMap { |
| | | position: absolute; |
| | | top: 10px; |
| | | left: calc(50% - 80px); |
| | | z-index: 2 !important; |
| | | } |
| | | } |
| | | </style> |