<!--
|
* @Author: shuishen 1109946754@qq.com
|
* @Date: 2023-10-11 16:01:58
|
* @LastEditors: shuishen 1109946754@qq.com
|
* @LastEditTime: 2023-11-29 14:17:09
|
* @FilePath: \web\business\src\components\OlMapBox\index.vue
|
* @Description:
|
*
|
* Copyright (c) 2023 by shuishen, All Rights Reserved.
|
-->
|
<template>
|
<div class="w100 h100" style="position: relative;">
|
<div id="OlMapBoxElement" class="w100 h100">
|
</div>
|
<div id="popup" class="ol-popup" v-show="isShowUnitInfoPopover">
|
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
|
<div id="popup-content">
|
<p>负责人:{{ unitData.securityLinkman }}</p>
|
<p>联系方式:{{ unitData.cell }}</p>
|
<p>派遣保安员数:{{ unitData.num }}</p>
|
<p>派遣单位行业:{{ unitData.professionName }}</p>
|
</div>
|
</div>
|
<div class="unit-select">
|
<el-select v-model="industryValue" multiple collapse-tags placeholder="请选择行业" clearable @change="industryChange">
|
<el-option v-for="item in industryOptions" :key="item.value" :label="item.label" :value="item.value">
|
</el-option>
|
</el-select>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import "ol/ol.css"
|
import OlView from "ol/View.js"
|
import OlLayerTile from "ol/layer/Tile.js"
|
import Overlay from "ol/Overlay.js"
|
import OlMap from "ol/Map.js"
|
import XYZ from "ol/source/XYZ"
|
import Cluster from "ol/source/Cluster"
|
import VectorLayer from "ol/layer/Vector"
|
import VectorSource from "ol/source/Vector"
|
import Feature from 'ol/Feature.js'
|
import Point from 'ol/geom/Point.js'
|
import { Icon, Style, Fill, Text, Stroke, Circle } from 'ol/style.js'
|
import { getAlldata, ProfessionList } from "@/api/dispatch/dispatch"
|
import { mapGetters } from "vuex"
|
import { mapState } from "vuex"
|
|
let mapView = null
|
let layersObjcect = {}
|
|
let baseMapLayer = {
|
yx: [],
|
sl: []
|
}
|
|
let unitInfoPopover = null
|
|
export default {
|
name: 'OlMapBox',
|
|
props: {
|
mapType: {
|
type: String,
|
default: 'sl'
|
},
|
|
mapContrast: {
|
type: String,
|
default: 'custom'
|
}
|
},
|
|
data () {
|
return {
|
publicPath: process.env.BASE_URL,
|
unitData: {},
|
isShowUnitInfoPopover: false,
|
industryOptions: [],
|
industryValue: [],
|
}
|
},
|
|
computed: {
|
...mapGetters(["permission", "userInfo"]),
|
|
...mapState({
|
userInfo: state => state.user.userInfo
|
})
|
},
|
mounted () {
|
const that = this
|
|
this.$nextTick(() => {
|
mapView = new OlMap({
|
target: 'OlMapBoxElement',
|
layers: [],
|
view: new OlView({
|
// 初始化中心点坐标,经纬度一会自己换一下
|
center: [112.85857823133, 35.496284586473],
|
zoom: 13,
|
projection: "EPSG:4326"
|
}),
|
})
|
|
mapView.on("singleclick", function (event) {
|
mapView.forEachFeatureAtPixel(
|
event.pixel,
|
(feature) => {
|
feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event })
|
}
|
)
|
})
|
|
mapView.getView().on('change:resolution', function () {
|
// console.log('mapView地图缩放事件')
|
})
|
|
that.getAlldata()//图标列表
|
that.ProfessionList()//行业列表
|
that.baseInitLayer(that.mapType)
|
})
|
},
|
|
methods: {
|
// 行业下拉选择值改变
|
industryChange () {
|
this.getAlldata()
|
},
|
|
// 获取派遣单位行业列表
|
ProfessionList () {
|
ProfessionList().then(res => {
|
this.industryOptions = []
|
res.data.data.forEach(item => {
|
this.industryOptions.push({ value: item.dictKey, label: item.dictValue })
|
})
|
})
|
},
|
|
// 图标点击事件
|
pqfwIconClick (e) {
|
this.generateMapPopup(e)
|
},
|
|
// 获取派遣服务列表
|
getAlldata () {
|
let params = {}
|
let roleName = this.userInfo.role_name
|
if (
|
roleName == "保安公司管理员" ||
|
roleName == "保安" ||
|
roleName == "分公司管理员"
|
) {
|
params.deptId = this.userInfo.dept_id
|
} else if (roleName == "公安管理员" || roleName == "administrator" || roleName == "民警") {
|
params.jurisdiction = this.userInfo.jurisdiction
|
}
|
params.profession = this.industryValue.length > 0 ? this.industryValue.join() : ''
|
getAlldata(params).then(res => {
|
this.$nextTick(() => {
|
this.mapRemoveLayer(['pqfwLayer'])
|
this.mapAddClusterLayer('pqfwLayer', 'img/map/unit.png', res.data.data, this.pqfwIconClick)
|
})
|
})
|
},
|
|
/**
|
* @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 || [32, 32],
|
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 }),
|
// offsetX: -60,
|
offsetY: 30
|
})
|
}
|
|
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]) {
|
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.longitude,
|
lat: item.latitude,
|
text: item.name,
|
url: imgUrl,
|
event: incident
|
}))
|
})
|
mapView.getView().animate({ // 只设置需要的属性即可
|
center: [positionData[0].longitude, positionData[0].latitude], // 中心点
|
// zoom: 18, // 缩放级别
|
rotation: undefined, // 缩放完成view视图旋转弧度
|
// duration: 1000 // 缩放持续时间,默认不需要设置
|
})
|
},
|
|
// 生成地图弹窗
|
generateMapPopup (e) {
|
const that = this
|
this.unitData = e
|
this.isShowUnitInfoPopover = true
|
var container = document.getElementById('popup')
|
var closer = document.getElementById('popup-closer')
|
|
// 创建popup
|
unitInfoPopover = new Overlay({
|
element: container,
|
autoPan: true,
|
positioning: 'bottom-center',
|
stopEvent: false,
|
autoPanAnimation: {
|
duration: 250
|
}
|
})
|
mapView.addOverlay(unitInfoPopover)
|
closer.onclick = function () {
|
unitInfoPopover.setPosition(undefined)
|
closer.blur()
|
return false
|
}
|
unitInfoPopover.setPosition([e.longitude, e.latitude])
|
},
|
|
|
}
|
}
|
</script>
|
|
<style lang='scss' scope>
|
.w100 {
|
width: 100%;
|
}
|
|
.h100 {
|
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: 34px;
|
left: -46px;
|
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: "✖";
|
}
|
|
.unit-select {
|
position: absolute;
|
top: 10px;
|
right: 20px;
|
}
|
</style>
|