| | |
| | | <!-- |
| | | * @Descripttion: |
| | | * @version: |
| | | * @Author: song |
| | | * @Date: 2021-04-08 15:14:57 |
| | | * @LastEditors: song |
| | | * @LastEditTime: 2021-04-24 11:59:43 |
| | | * @Description: 绘制图形统计圈内点数 |
| | | * @Author: Dragon |
| | | * @Date: 2020-12-21 13:19:47 |
| | | * @LastEditTime: 2020-12-21 15:03:27 |
| | | * @LastEditors: Dragon |
| | | --> |
| | | |
| | | <template> |
| | | <div id="track_map" style="height: 100%"></div> |
| | | <div> |
| | | <div class="query-wrap"> |
| | | <el-button type="primary" @click="drawStart('Polygon')"> |
| | | {{ isDraw ? "绘制区域查询人数" : "重新绘制" }} |
| | | </el-button> |
| | | </div> |
| | | <div id="map"></div> |
| | | </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 { |
| | | // 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 VectorLayer from "ol/layer/Vector"; |
| | | import VectorSource from "ol/source/Vector"; |
| | | import WMTS from "ol/source/WMTS"; |
| | | |
| | | import WMTSTileGrid from "ol/tilegrid/WMTS"; |
| | | |
| | | import Feature from "ol/Feature.js"; |
| | | import Point from "ol/geom/Point.js"; |
| | | import LineString from "ol/geom/LineString.js"; |
| | | import { Icon, Style, Fill, Stroke } from "ol/style.js"; |
| | | |
| | | import { getWidth, getTopLeft } from "ol/extent"; |
| | | |
| | | import { get as getProjection } from "ol/proj"; |
| | | import XYZ from "ol/source/XYZ"; |
| | | |
| | | import start from "@/assets/img/start.png"; |
| | | |
| | | import { Map, View, Feature } from "ol"; |
| | | import { Image as ImageLayer, Vector as VectorLayer } from "ol/layer"; |
| | | import { ImageStatic, Vector as VectorSource } from "ol/source"; |
| | | import { getCenter } from "ol/extent"; |
| | | import { Projection } from "ol/proj"; |
| | | 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 img from "@/assets/img/car.png"; |
| | | |
| | | export default { |
| | | name: "Map", |
| | | data() { |
| | | return { |
| | | gunAddlayer: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | peopleAddlayer: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | carAddlayer: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | peopleLineAddlayer: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | startPoint: new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 22, |
| | | source: new VectorSource(), |
| | | }), |
| | | ol2d: null, |
| | | 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)", |
| | | }), |
| | | }), |
| | | ], |
| | | persons: [], |
| | | polygon: [], |
| | | polygonPersons: [], |
| | | features: [], |
| | | feature: null, |
| | | vectorSource: new VectorSource(), |
| | | timer: null, |
| | | }; |
| | | }, |
| | | mounted() { |
| | | // 本地开发使用; |
| | | this.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", // 行政区划 |
| | | }), |
| | | }), |
| | | // , |
| | | // new OlLayerTile({ |
| | | // zIndex: 5, |
| | | // title: '道路+中文注记', |
| | | // source: new XYZ({ |
| | | // url: 'http://t3.tianditu.com/DataServer?T=cta_w&x={x}&y={y}&l={z}&tk=e9533f5acb2ac470b07f406a4d24b4f0' // 注记 |
| | | // }) |
| | | // }) |
| | | ], |
| | | |
| | | // 注意地图控件的写法 |
| | | controls: defaults().extend([ |
| | | new FullScreen(), |
| | | new ScaleLine(), |
| | | new MousePosition(), |
| | | new Rotate(), |
| | | new Attribution(), |
| | | ]), |
| | | target: "track_map", |
| | | view: new OlView({ |
| | | center: [0, 0], |
| | | zoom: 2, |
| | | projection: "EPSG:4326", |
| | | }), |
| | | }); |
| | | |
| | | var projection = getProjection("EPSG:4326"); |
| | | var projectionExtent = projection.getExtent(); |
| | | var size = getWidth(projectionExtent) / 256; |
| | | var resolutions = []; |
| | | for (var z = 2; z < 19; ++z) { |
| | | //计算比例尺 |
| | | resolutions[z] = size / Math.pow(2, z); |
| | | } |
| | | |
| | | // 正式服务器上使用 |
| | | // this.ol2d = new OlMap({ |
| | | // layers: [ |
| | | // new OlLayerTile({//矢量地图 |
| | | |
| | | // source: new WMTS({ |
| | | // url: "http://47.49.21.207:7001/PGIS_S_TileMapServer/Maps/YX", |
| | | // layer: "JX14YGJCIMGL7_L14", |
| | | // style: "default", |
| | | // matrixSet: "JX14YGJCIMGL7_L14", |
| | | // format: "image/png", |
| | | // wrapX: true, |
| | | // tileGrid: new WMTSTileGrid({ |
| | | // origin: getTopLeft(projectionExtent), |
| | | // //resolutions: res.slice(0, 15), |
| | | // resolutions: resolutions, |
| | | // matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] |
| | | // }) |
| | | // }), |
| | | |
| | | // }) |
| | | // ], |
| | | |
| | | // // 注意地图控件的写法 |
| | | // controls: defaults().extend([ |
| | | // new FullScreen(), |
| | | // new ScaleLine(), |
| | | // // new MousePosition(), |
| | | // new Rotate(), |
| | | // new Attribution() |
| | | // ]), |
| | | // target: 'track_map', |
| | | // view: new OlView({ |
| | | // center: [115.85883507433789, 28.708432053474827], |
| | | // projection: projection, |
| | | // zoom: 11, |
| | | // maxZoom: 15, |
| | | // minZoom: 1 |
| | | |
| | | // }) |
| | | // }) |
| | | |
| | | this.parentParameter(); |
| | | |
| | | window.ol2d = this.ol2d; |
| | | |
| | | var view = this.ol2d.getView(); |
| | | |
| | | view.setCenter([115.85883507433789, 28.708432053474827]); |
| | | |
| | | view.setZoom(13); |
| | | |
| | | this.ol2d.addLayer(this.gunAddlayer); |
| | | this.ol2d.addLayer(this.peopleAddlayer); |
| | | this.ol2d.addLayer(this.carAddlayer); |
| | | this.ol2d.addLayer(this.peopleLineAddlayer); |
| | | this.ol2d.addLayer(this.startPoint); |
| | | watch: { |
| | | persons(val) { |
| | | if (val) { |
| | | this.setFeature(); |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | addEntitys(item, icon, scale, name, type) { |
| | | this[type].getSource().clear(); |
| | | |
| | | const iconFeature = new Feature({ |
| | | geometry: new Point([Number(item.LGTD), Number(item.LTTD)]), |
| | | name: name, |
| | | attributes: item, |
| | | // 初始化地图 |
| | | initMap() { |
| | | let extent = [0, 0, this.imgx, this.imgy]; |
| | | let projection = new Projection({ |
| | | extent: extent, |
| | | }); |
| | | |
| | | const iconStyle = new Style({ |
| | | // text: new Text({ // 字体, 未成功, 浪费许多时间 |
| | | // font: 'Normal ' + 12 + 'px ' + 'iconfont', |
| | | // text: "\e645", |
| | | // fill: new Fill({ color: "green" }), |
| | | // }), |
| | | |
| | | image: new Icon({ |
| | | scale: scale, |
| | | opacity: 1, |
| | | src: icon, |
| | | // src: require('../../assets/Mark.png') |
| | | let $this = this; |
| | | // 默认地图 |
| | | let mapLayer = new ImageLayer({ |
| | | source: new ImageStatic({ |
| | | url: staticMap, |
| | | projection: projection, |
| | | imageExtent: extent, |
| | | }), |
| | | |
| | | // new CircleStyle({ // 普通样式 |
| | | // radius: 6, |
| | | // fill: new Fill({ |
| | | // color: 'rgba(200, 155, 155, 0.8)' |
| | | // }), |
| | | // stroke: new Stroke({ |
| | | // color: 'black', |
| | | // width: 0.3, |
| | | // }) |
| | | // }), |
| | | }); |
| | | |
| | | iconFeature.setStyle(iconStyle); |
| | | |
| | | this[type].getSource().addFeature(iconFeature); |
| | | |
| | | this.flyTo(Number(item.LGTD), Number(item.LTTD), 13); |
| | | }, |
| | | |
| | | addLines(arr) { |
| | | this.addEntity(arr[0][0], arr[0][1]); |
| | | this.peopleLineAddlayer.getSource().clear(); |
| | | // 点坐标 |
| | | var lineCoords = arr; // 线里点的集合 |
| | | |
| | | // 要素 |
| | | // 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), |
| | | |
| | | // 绘制点 |
| | | let featureLayer = new VectorLayer({ |
| | | source: this.vectorSource, |
| | | }); |
| | | |
| | | 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, |
| | | }), |
| | | }) |
| | | ); |
| | | |
| | | this.peopleLineAddlayer.getSource().addFeature(feature_LineString); |
| | | |
| | | this.flyTo( |
| | | arr[Math.ceil(arr.length / 2)][0], |
| | | arr[Math.ceil(arr.length / 2)][1], |
| | | 13 |
| | | ); |
| | | }, |
| | | |
| | | addEntity(LGTD, LTTD) { |
| | | this.startPoint.getSource().clear(); |
| | | |
| | | const iconFeature = new Feature({ |
| | | geometry: new Point([LGTD, LTTD]), |
| | | name: "起始点", |
| | | }); |
| | | |
| | | const iconStyle = new Style({ |
| | | // text: new Text({ // 字体, 未成功, 浪费许多时间 |
| | | // font: 'Normal ' + 12 + 'px ' + 'iconfont', |
| | | // text: "\e645", |
| | | // fill: new Fill({ color: "green" }), |
| | | // }), |
| | | |
| | | image: new Icon({ |
| | | anchor: [0.5, 170], //锚点 |
| | | anchorOrigin: "top-left", //锚点源 |
| | | anchorXUnits: "fraction", //锚点X值单位 |
| | | anchorYUnits: "pixels", //锚点Y值单位 |
| | | offsetOrigin: "top-left", |
| | | scale: 0.2, |
| | | opacity: 1, |
| | | src: start, |
| | | // src: require('../../assets/Mark.png') |
| | | |
| | | this.map = new Map({ |
| | | target: "map", |
| | | layers: [ |
| | | mapLayer, // 展示地图层 |
| | | featureLayer, // 点 |
| | | ], |
| | | view: new View({ |
| | | projection: projection, |
| | | center: getCenter(extent), |
| | | zoom: 2, |
| | | maxZoom: 18, |
| | | }), |
| | | |
| | | // new CircleStyle({ // 普通样式 |
| | | // radius: 6, |
| | | // fill: new Fill({ |
| | | // color: 'rgba(200, 155, 155, 0.8)' |
| | | // }), |
| | | // stroke: new Stroke({ |
| | | // color: 'black', |
| | | // width: 0.3, |
| | | // }) |
| | | // }), |
| | | }); |
| | | |
| | | iconFeature.setStyle(iconStyle); |
| | | |
| | | this.startPoint.getSource().addFeature(iconFeature); |
| | | |
| | | this.source = new VectorSource({ wrapX: false }); |
| | | this.vector = new VectorLayer({ |
| | | source: this.source, |
| | | style: this.styles, |
| | | }); |
| | | this.map.addLayer(this.vector); |
| | | }, |
| | | |
| | | clearLine() { |
| | | this.peopleLineAddlayer.getSource().clear(); |
| | | this.startPoint.getSource().clear(); |
| | | |
| | | // 点 |
| | | setFeature() { |
| | | let that = this; |
| | | that.features = []; |
| | | that.vectorSource.clear(); |
| | | that.persons.map((item) => { |
| | | that.feature = new Feature({ |
| | | geometry: new Point([item.x, item.y]), |
| | | name: item.name, |
| | | }); |
| | | // 设置Feature的样式,使用小旗子图标 |
| | | that.feature.setStyle( |
| | | new Style({ |
| | | image: new Icon({ |
| | | anchor: [0, 1], |
| | | src: img, |
| | | }), |
| | | text: new Text({ |
| | | // 位置 |
| | | textAlign: "center", |
| | | // 基准线 |
| | | textBaseline: "middle", |
| | | // 文字样式 |
| | | font: "normal 20px 微软雅黑", |
| | | // 文本内容 |
| | | text: item.name, |
| | | // 文本填充样式(即文字颜色) |
| | | fill: new Fill({ color: "#aa3300" }), |
| | | stroke: new Stroke({ color: "#ffcc33", width: 2 }), |
| | | }), |
| | | }) |
| | | ); |
| | | that.features.push(that.feature); |
| | | }); |
| | | that.vectorSource.addFeatures(that.features); |
| | | }, |
| | | |
| | | flyTo(lgtd, lttd, size) { |
| | | var view = this.ol2d.getView(); |
| | | |
| | | view.setCenter([lgtd, lttd]); |
| | | |
| | | view.setZoom(size); |
| | | |
| | | // 开始绘制多边形 |
| | | drawStart(type) { |
| | | let that = this; |
| | | if (this.isDraw) { |
| | | this.isDraw = false; |
| | | this.draw = new Draw({ |
| | | source: this.source, |
| | | type: type, |
| | | }); |
| | | this.map.addInteraction(this.draw); |
| | | this.draw.on("drawend", function (evt) { |
| | | that.drawingEnd(evt); |
| | | }); |
| | | } else { |
| | | this.source.clear(); |
| | | this.map.removeInteraction(this.draw); |
| | | this.isDraw = true; |
| | | this.polygon = []; |
| | | this.polygonPersons = []; |
| | | } |
| | | }, |
| | | |
| | | parentParameter() { |
| | | this.$emit("childParameter", this.ol2d); |
| | | |
| | | // 构建多边形结束 |
| | | drawingEnd(evt) { |
| | | let that = this; |
| | | const geo = evt.feature.getGeometry(); |
| | | const t = geo.getType(); |
| | | if (t === "Polygon") { |
| | | // 获取坐标点 |
| | | const points = geo.getCoordinates(); |
| | | points[0].map((item) => { |
| | | 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.$message({ |
| | | type: "success", |
| | | message: `区域内有${this.polygonPersons.length}人`, |
| | | }); |
| | | console.warn(this.polygonPersons, `区域内有${this.polygonPersons.length}人`); |
| | | this.map.removeInteraction(this.draw); |
| | | } |
| | | }, |
| | | |
| | | // 验证点是否在区域内 |
| | | 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++; |
| | | } |
| | | } |
| | | } |
| | | if (num % 2 != 0) return true; |
| | | return false; |
| | | }, |
| | | }, |
| | | 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); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | #map { |
| | | width: 100%; |
| | | height: calc(100vh - 50px); |
| | | } |
| | | </style> |