<!--
|
* @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">
|
<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>
|
</template>
|
|
<script>
|
// import OLCesium from "ol-cesium"
|
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,
|
} 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'
|
|
import OlLayerVectorTile from "ol/layer/VectorTile.js"
|
import OlMap from "ol/Map.js"
|
import OlProjection from "ol/proj/Projection.js"
|
import OlMVT from "ol/format/MVT.js"
|
import OlUnits from "ol/proj/Units.js"
|
import OlFeature from "ol/Feature"
|
|
import { get as projGet } from "ol/proj.js"
|
// c
|
|
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 TileArcGISRest from "ol/source/TileArcGISRest"
|
import TilegridTileGrid from "ol/tilegrid/TileGrid"
|
|
import GeoJSON from "ol/format/GeoJSON"
|
|
import Feature from 'ol/Feature.js'
|
import Point from 'ol/geom/Point.js'
|
import { Icon, Style, Fill, Text, Stroke, Circle } from 'ol/style.js'
|
|
|
let mapView = null
|
let layersObjcect = {}
|
|
let baseMapLayer = {
|
yx: [],
|
sl: []
|
}
|
|
let livePersonInfoPopover = null
|
|
let options,
|
epsgcode,
|
isMvt = false
|
|
let isMapResource = true
|
export default {
|
name: 'OlMapBox',
|
|
props: {
|
mapType: {
|
type: String,
|
default: 'sl'
|
},
|
|
mapContrast: {
|
type: String,
|
default: 'custom'
|
}
|
},
|
|
data () {
|
return {
|
publicPath: process.env.BASE_URL,
|
livePersonData: {},
|
isShowLivePersonInfoPopover: false
|
}
|
},
|
|
|
mounted () {
|
const that = this
|
|
this.$nextTick(() => {
|
mapView = new OlMap({
|
target: 'OlMapBoxElement',
|
layers: [],
|
view: new OlView({
|
// 初始化中心点坐标,经纬度一会自己换一下
|
center: [112.85857823133, 35.496284586473],
|
zoom: 18,
|
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.$emit('getlivePersonLocationList')
|
})
|
|
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 || [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
|
console.log(layersObjcect, layerName, positionData, "+++++++++++++")
|
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,
|
text: item.realName,
|
url: imgUrl,
|
event: incident
|
}))
|
})
|
mapView.getView().animate({ // 只设置需要的属性即可
|
center: [positionData[0].lng, positionData[0].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%;
|
}
|
|
.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: "✖";
|
}
|
</style>
|