From 4c5ccd55411d61c379bc17abfde2699f50da20d3 Mon Sep 17 00:00:00 2001
From: guanqb <18720758508@163.com>
Date: Fri, 22 Dec 2023 18:18:30 +0800
Subject: [PATCH] 保安员位置接口对接、生成图标点击弹窗展示
---
src/views/check/components/OlMapBox.vue | 742 ++++++++++++++++++++++++++++++++-------------------------
1 files changed, 417 insertions(+), 325 deletions(-)
diff --git a/src/views/check/components/OlMapBox.vue b/src/views/check/components/OlMapBox.vue
index 1957c7a..add9d6b 100644
--- a/src/views/check/components/OlMapBox.vue
+++ b/src/views/check/components/OlMapBox.vue
@@ -9,10 +9,19 @@
* Copyright (c) 2023 by shuishen, All Rights Reserved.
-->
<template>
- <div class="w100 h100">
- <div id="OlMapBoxElement" class="w100 h100">
+ <div class="w100 h100">
+ <div id="OlMapBoxElement" class="w100 h100">
+ </div>
+ <div id="popup" class="ol-popup" v-show="isShowLivePersonInfoPopover">
+ <a href="#" id="popup-closer" class="ol-popup-closer"></a>
+ <div id="popup-content">
+ <p>名称:{{ livePersonData.realName }}</p>
+ <p>所属公司:{{ livePersonData.deptName }}</p>
+ <p>派遣单位:{{ livePersonData.dispatchCompany }}</p>
+ <p>更新时间:{{ livePersonData.recordTime }}</p>
+ </div>
+ </div>
</div>
- </div>
</template>
<script>
@@ -20,31 +29,32 @@
import "ol/ol.css"
import OlView from "ol/View.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,
+ // 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 OlSourceOSM from "ol/source/OSM.js"
import OlLayerTile from "ol/layer/Tile.js"
+import Overlay from "ol/Overlay.js"
import { Image as ImageLayer } from 'ol/layer'
import ImageStatic from 'ol/source/ImageStatic.js'
@@ -80,332 +90,414 @@
let layersObjcect = {}
let baseMapLayer = {
- yx: [],
- sl: []
+ yx: [],
+ sl: []
}
+
+let livePersonInfoPopover = null
+
let options,
- epsgcode,
- isMvt = false
+ epsgcode,
+ isMvt = false
let isMapResource = true
export default {
- name: 'OlMapBox',
+ name: 'OlMapBox',
- props: {
- mapType: {
- type: String,
- default: 'sl'
- },
+ props: {
+ mapType: {
+ type: String,
+ default: 'sl'
+ },
- mapContrast: {
- type: String,
- default: 'custom'
- }
- },
-
- data () {
- return {
- publicPath: process.env.BASE_URL,
- }
- },
-
-
- mounted () {
- const that = this
-
- this.$nextTick(() => {
- mapView = new OlMap({
- target: 'OlMapBoxElement',
- layers: [],
- view: new OlView({
- // 初始化中心点坐标,经纬度一会自己换一下
- center: [113, 24],
- zoom: 18,
- projection: "EPSG:4326"
- }),
- })
-
- mapView.on("singleclick", function (event) {
- mapView.forEachFeatureAtPixel(
- event.pixel,
- (feature) => {
- feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event })
- }
- )
- })
-
- that.baseInitLayer(that.mapType)
-
-
- this.mapAddClusterLayer(
- 'livePersonLocationLayer',
- '/public/img/map/location',
- [{lng: 113, lat: 24}, {lng: 115, lat:24 }],
- (e) => { },
- )
- })
- },
-
- methods: {
- /**
- * @description: 底图加载
- * @param {*} type
- * @return {*}
- */
- baseInitLayer (type) {
- if (baseMapLayer.yx.length) {
- baseMapLayer.yx.forEach(item => {
- mapView.removeLayer(item)
- })
- baseMapLayer.yx = []
- }
-
- if (baseMapLayer.sl.length) {
- baseMapLayer.sl.forEach(item => {
- mapView.removeLayer(item)
- })
- baseMapLayer.sl = []
- }
-
- if (type == 'yx') {
- let yxImgW = new OlLayerTile({
- zIndex: 1,
- title: '影像',
- source: new XYZ({
- url: 'https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
- })
- })
-
- mapView.addLayer(yxImgW)
-
- baseMapLayer.yx.push(yxImgW)
-
- let yxCvaW = new OlLayerTile({
- zIndex: 2,
- title: '影像标注',
- source: new XYZ({
- url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
- })
- })
-
- mapView.addLayer(yxCvaW)
-
- baseMapLayer.yx.push(yxCvaW)
- } else if (type == 'sl') {
- let slVecW = new OlLayerTile({
- zIndex: 2,
- title: '矢量',
- source: new XYZ({
- url: 'https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
- })
- })
-
- mapView.addLayer(slVecW)
-
- baseMapLayer.sl.push(slVecW)
-
- let slCvaW = new OlLayerTile({
- zIndex: 2,
- title: '矢量标注',
- source: new XYZ({
- url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
- })
- })
-
- mapView.addLayer(slCvaW)
-
- baseMapLayer.sl.push(slVecW)
- }
- },
-
- // javascript 转换
- lonLat2Mercator (lonlat) {
- var mercator = {
- x: 0,
- y: 0
- }
- var earthRad = 6378137.0
- mercator.x = lonlat.lng * Math.PI / 180 * earthRad
- var a = lonlat.lat * Math.PI / 180
- mercator.y = earthRad / 2 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)))
- return mercator
- },
-
- getCurItemFeature (params) {
- const iconFeature = new Feature({
- geometry: new Point([Number(params.lng), Number(params.lat)]),
- attributes: params.item
- })
-
- let styleOptions = {
- cursor: 'pointer',
- }
-
- if (params.url) {
- styleOptions.image = new Icon({
- scale: params.scale || 1,
- imgSize: params.imgSize || [160, 221],
- src: params.url,
- })
- }
-
- if (params.text) {
- let textElement = document.createElement('span')
- textElement.innerHTML = params.text
-
- let color = '#0000FF'
-
- styleOptions.text = new Text({
- // 对齐方式
- textAlign: 'center',
- // 文本基线
- textBaseline: 'middle',
- text: textElement.innerHTML,
- font: '14px Arial',
- fill: new Fill({
- color: 'white'
- }),
- // 填充背景
- backgroundFill: new Fill({
- color: color
- }),
- padding: [2, 5, 2, 5],
- stroke: new Stroke({ color: '#00000000', width: 1 })
- })
- }
-
- iconFeature.setStyle(new Style(styleOptions))
-
- iconFeature.on('click', (e) => {
- if (params.event) {
- params.event(e.target.values_.attributes.attr)
+ mapContrast: {
+ type: String,
+ default: 'custom'
}
- })
-
- return iconFeature
},
- /**
- * 删除图层
- * @param {*} layerName 图层名称
- */
- mapRemoveLayer (layerNames) {
- layerNames.forEach(item => {
- if (layersObjcect[item] && layersObjcect[item] != null) {
- mapView.removeLayer(layersObjcect[item])
- delete layersObjcect[item]
+ data () {
+ return {
+ publicPath: process.env.BASE_URL,
+ livePersonData: {},
+ isShowLivePersonInfoPopover: false
}
-
- if (layersObjcect[item + 'ONE'] && layersObjcect[item + 'ONE'] != null) {
- mapView.removeLayer(layersObjcect[item + 'ONE'])
- delete layersObjcect[item + 'ONE']
- }
-
- if (layersObjcect[item + 'TWO'] && layersObjcect[item + 'TWO'] != null) {
- mapView.removeLayer(layersObjcect[item + 'TWO'])
- delete layersObjcect[item + 'TWO']
- }
- })
},
- // 添加聚合图层的新模式,水库点分布
- mapAddClusterLayer (layerName, imgUrl, positionData, incident = (e) => { }, type = '') {
- const that = this
- if (!layersObjcect[layerName]) {
- if (type == 'cluster') {
- let source = new VectorSource()
+ mounted () {
+ const that = this
- positionData.forEach(item => {
- source.addFeature(that.getCurItemFeature({
- item,
- lng: item.lng,
- lat: item.lat,
- url: imgUrl,
- event: incident
- }))
- })
-
- let layer = new Cluster({
- source: source,
- distance: 100
- })
-
- layersObjcect[layerName] = new VectorLayer({
- source: layer,
- zIndex: 24,
- style: (feature, resolution) => {
- let size = feature.get('features').length
-
- let radius = 10
-
- if (size > 900) {
- radius = 19
- } else if (size > 600) {
- radius = 16
- } else if (size > 400) {
- radius = 13
- }
-
- let style = new Style({
- image: new Circle({
- radius: radius,
- stroke: new Stroke({
- color: 'blue',
- width: 1
- }),
- fill: new Fill({
- color: 'blue'
- })
+ this.$nextTick(() => {
+ mapView = new OlMap({
+ target: 'OlMapBoxElement',
+ layers: [],
+ view: new OlView({
+ // 初始化中心点坐标,经纬度一会自己换一下
+ center: [113, 24],
+ zoom: 18,
+ projection: "EPSG:4326"
}),
- text: new Text({
- text: size.toString(),
- fill: new Fill({
- color: 'white'
- })
- })
- })
+ })
- return style
- }
- })
+ mapView.on("singleclick", function (event) {
+ mapView.forEachFeatureAtPixel(
+ event.pixel,
+ (feature) => {
+ feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event })
+ }
+ )
+ })
- mapView.addLayer(layersObjcect[layerName])
-
- return
- } else {
- layersObjcect[layerName] = new VectorLayer({
- // 图标图层
- zIndex: 24,
- minZoom: 12,
- source: new VectorSource(),
- })
- }
-
- mapView.addLayer(layersObjcect[layerName])
- }
-
- positionData.forEach(item => {
- layersObjcect[layerName].getSource().addFeature(that.getCurItemFeature({
- item,
- lng: item.lng,
- lat: item.lat,
- url: imgUrl,
- event: incident
- }))
- })
+ that.baseInitLayer(that.mapType)
+ })
},
- },
+
+ methods: {
+ /**
+ * @description: 底图加载
+ * @param {*} type
+ * @return {*}
+ */
+ baseInitLayer (type) {
+ if (baseMapLayer.yx.length) {
+ baseMapLayer.yx.forEach(item => {
+ mapView.removeLayer(item)
+ })
+ baseMapLayer.yx = []
+ }
+
+ if (baseMapLayer.sl.length) {
+ baseMapLayer.sl.forEach(item => {
+ mapView.removeLayer(item)
+ })
+ baseMapLayer.sl = []
+ }
+
+ if (type == 'yx') {
+ let yxImgW = new OlLayerTile({
+ zIndex: 1,
+ title: '影像',
+ source: new XYZ({
+ url: 'https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
+ })
+ })
+
+ mapView.addLayer(yxImgW)
+
+ baseMapLayer.yx.push(yxImgW)
+
+ let yxCvaW = new OlLayerTile({
+ zIndex: 2,
+ title: '影像标注',
+ source: new XYZ({
+ url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
+ })
+ })
+
+ mapView.addLayer(yxCvaW)
+
+ baseMapLayer.yx.push(yxCvaW)
+ } else if (type == 'sl') {
+ let slVecW = new OlLayerTile({
+ zIndex: 2,
+ title: '矢量',
+ source: new XYZ({
+ url: 'https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
+ })
+ })
+
+ mapView.addLayer(slVecW)
+
+ baseMapLayer.sl.push(slVecW)
+
+ let slCvaW = new OlLayerTile({
+ zIndex: 2,
+ title: '矢量标注',
+ source: new XYZ({
+ url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
+ })
+ })
+
+ mapView.addLayer(slCvaW)
+
+ baseMapLayer.sl.push(slVecW)
+ }
+ },
+
+ // javascript 转换
+ lonLat2Mercator (lonlat) {
+ var mercator = {
+ x: 0,
+ y: 0
+ }
+ var earthRad = 6378137.0
+ mercator.x = lonlat.lng * Math.PI / 180 * earthRad
+ var a = lonlat.lat * Math.PI / 180
+ mercator.y = earthRad / 2 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)))
+ return mercator
+ },
+
+ // 生成图标图层
+ getCurItemFeature (params) {
+ const iconFeature = new Feature({
+ geometry: new Point([Number(params.lng), Number(params.lat)]),
+ attributes: params.item
+ })
+
+ let styleOptions = {
+ cursor: 'pointer',
+ }
+
+ if (params.url) {
+ styleOptions.image = new Icon({
+ scale: params.scale || 1,
+ imgSize: params.imgSize || [160, 221],
+ src: params.url,
+ })
+ }
+
+ if (params.text) {
+ let textElement = document.createElement('span')
+ textElement.innerHTML = params.text
+
+ let color = '#0000FF'
+
+ styleOptions.text = new Text({
+ // 对齐方式
+ textAlign: 'center',
+ // 文本基线
+ textBaseline: 'middle',
+ text: textElement.innerHTML,
+ font: '14px Arial',
+ fill: new Fill({
+ color: 'white'
+ }),
+ // 填充背景
+ backgroundFill: new Fill({
+ color: color
+ }),
+ padding: [2, 5, 2, 5],
+ stroke: new Stroke({ color: '#00000000', width: 1 })
+ })
+ }
+
+ iconFeature.setStyle(new Style(styleOptions))
+
+ iconFeature.on('click', (e) => {
+ if (params.event) {//icon事件参数
+ params.event(e.target.values_.attributes)//点击事件触发事件并传参
+ }
+ })
+ return iconFeature
+ },
+
+ /**
+ * 删除图层
+ * @param {*} layerName 图层名称
+ */
+ mapRemoveLayer (layerNames) {
+ layerNames.forEach(item => {
+ if (layersObjcect[item] && layersObjcect[item] != null) {
+ mapView.removeLayer(layersObjcect[item])
+ delete layersObjcect[item]
+ }
+
+ if (layersObjcect[item + 'ONE'] && layersObjcect[item + 'ONE'] != null) {
+ mapView.removeLayer(layersObjcect[item + 'ONE'])
+ delete layersObjcect[item + 'ONE']
+ }
+
+ if (layersObjcect[item + 'TWO'] && layersObjcect[item + 'TWO'] != null) {
+ mapView.removeLayer(layersObjcect[item + 'TWO'])
+ delete layersObjcect[item + 'TWO']
+ }
+ })
+ },
+
+ // 添加聚合图层的新模式,水库点分布
+ mapAddClusterLayer (layerName, imgUrl, positionData, incident = (e) => { }, type = '') {
+ const that = this
+
+ if (!layersObjcect[layerName]) {
+ if (type == 'cluster') {
+ let source = new VectorSource()
+
+ positionData.forEach(item => {
+ source.addFeature(that.getCurItemFeature({
+ item,
+ lng: item.lng,
+ lat: item.lat,
+ url: imgUrl,
+ event: incident
+ }))
+ })
+
+ let layer = new Cluster({
+ source: source,
+ distance: 100
+ })
+
+ layersObjcect[layerName] = new VectorLayer({
+ source: layer,
+ zIndex: 24,
+ style: (feature, resolution) => {
+ let size = feature.get('features').length
+
+ let radius = 10
+
+ if (size > 900) {
+ radius = 19
+ } else if (size > 600) {
+ radius = 16
+ } else if (size > 400) {
+ radius = 13
+ }
+
+ let style = new Style({
+ image: new Circle({
+ radius: radius,
+ stroke: new Stroke({
+ color: 'blue',
+ width: 1
+ }),
+ fill: new Fill({
+ color: 'blue'
+ })
+ }),
+ text: new Text({
+ text: size.toString(),
+ fill: new Fill({
+ color: 'white'
+ })
+ })
+ })
+
+ return style
+ }
+ })
+
+ mapView.addLayer(layersObjcect[layerName])
+
+ return
+ } else {
+ layersObjcect[layerName] = new VectorLayer({
+ // 图标图层
+ zIndex: 24,
+ minZoom: 12,
+ source: new VectorSource(),
+ })
+ }
+
+ mapView.addLayer(layersObjcect[layerName])
+ }
+
+ positionData.forEach(item => {
+ layersObjcect[layerName].getSource().addFeature(that.getCurItemFeature({
+ item,
+ lng: item.lng,
+ lat: item.lat,
+ url: imgUrl,
+ event: incident
+ }))
+ mapView.getView().animate({ // 只设置需要的属性即可
+ center: [item.lng, item.lat], // 中心点
+ zoom: 18, // 缩放级别
+ rotation: undefined, // 缩放完成view视图旋转弧度
+ duration: 1000 // 缩放持续时间,默认不需要设置
+ })
+ })
+
+ },
+
+ // 生成地图弹窗
+ generateMapPopup (e) {
+ const that = this
+ this.livePersonData = e
+ this.isShowLivePersonInfoPopover = true
+ var container = document.getElementById('popup')
+ var closer = document.getElementById('popup-closer')
+
+ // 创建popup
+ livePersonInfoPopover = new Overlay({
+ element: container,
+ autoPan: true,
+ positioning: 'bottom-center',
+ stopEvent: false,
+ autoPanAnimation: {
+ duration: 250
+ }
+ })
+ mapView.addOverlay(livePersonInfoPopover)
+ closer.onclick = function () {
+ livePersonInfoPopover.setPosition(undefined)
+ closer.blur()
+ return false
+ }
+ livePersonInfoPopover.setPosition([e.lng, e.lat])
+ },
+
+
+ }
}
</script>
<style lang='scss' scope>
-
.w100 {
- width: 100%;
+ width: 100%;
}
.h100 {
- height: 100%;
+ height: 100%;
+}
+
+.ol-popup {
+ position: absolute;
+ background-color: white;
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
+ filter: drop-shadow(0 1px 4px #FFC125);
+ padding: 15px;
+ border-radius: 10px;
+ border: 1px solid #cccccc;
+ bottom: 130px;
+ left: -114px;
+ min-width: 300px;
+}
+
+.ol-popup:after,
+.ol-popup:before {
+ top: 100%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+
+.ol-popup:after {
+ border-top-color: white;
+ border-width: 10px;
+ left: 48px;
+ margin-left: -10px;
+}
+
+.ol-popup:before {
+ border-top-color: #cccccc;
+ border-width: 11px;
+ left: 48px;
+ margin-left: -11px;
+}
+
+.ol-popup-closer {
+ text-decoration: none;
+ position: absolute;
+ top: 2px;
+ right: 8px;
+ color: red;
+}
+
+.ol-popup-closer:after {
+ content: "✖";
}
</style>
--
Gitblit v1.9.3