|
|
@@ -3,7 +3,8 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import { Map, View } from 'ol'
|
|
|
+ import { useModal } from 'naive-ui'
|
|
|
+ import { Map, View, Overlay } from 'ol'
|
|
|
import SourceVector from 'ol/source/Vector'
|
|
|
import LayerVector from 'ol/layer/Vector'
|
|
|
import Cluster from 'ol/source/Cluster.js'
|
|
|
@@ -11,16 +12,19 @@
|
|
|
// import OSM from "ol/source/OSM";
|
|
|
import { Circle, Fill, Stroke, Style, Text, Icon } from 'ol/style'
|
|
|
import { Zoom } from 'ol/control'
|
|
|
- import { fromLonLat } from 'ol/proj'
|
|
|
+ import { fromLonLat, toLonLat } from 'ol/proj'
|
|
|
import { boundingExtent } from 'ol/extent.js'
|
|
|
+ import { useOutsideHomeStore } from '@/stores/modules/home'
|
|
|
import Feature from 'ol/Feature'
|
|
|
import Point from 'ol/geom/Point'
|
|
|
import GeoJSON from 'ol/format/GeoJSON'
|
|
|
import videoIcon from '@/assets/images/video-icon.png'
|
|
|
- import { useOutsideHomeStore } from '@/stores/modules/home'
|
|
|
+ import AddDevice from './components/addDevice.vue'
|
|
|
|
|
|
const useHomeStore = useOutsideHomeStore()
|
|
|
+ const { API_MR_CAMERA_GET, API_MR_VIDEO_LIST_GET } = useRequest()
|
|
|
|
|
|
+ const modal = useModal()
|
|
|
const map = shallowRef(null)
|
|
|
|
|
|
const labelStyle = new Style({
|
|
|
@@ -277,23 +281,33 @@
|
|
|
}
|
|
|
|
|
|
const currentDis = ref(150)
|
|
|
+ // 根据points创建一个新的数据源和要素数组,
|
|
|
+ const vectorSource = new SourceVector()
|
|
|
// 根据数据创建聚合图层
|
|
|
- const createCluster = (points, zindex) => {
|
|
|
- const features = points.map((e) => {
|
|
|
- // ol.proj.fromLonLat用于将经纬度坐标从 WGS84 坐标系转换为地图投影坐标系
|
|
|
+ const createCluster = (points, custom = {}, zindex) => {
|
|
|
+ if (custom.type === 'add') {
|
|
|
const feature = new Feature({
|
|
|
- geometry: new Point(fromLonLat(e)),
|
|
|
+ geometry: new Point(fromLonLat(points[0])),
|
|
|
custom: {
|
|
|
- id: Math.ceil(Math.random() * 100000)
|
|
|
+ ...custom
|
|
|
}
|
|
|
})
|
|
|
- return feature
|
|
|
- })
|
|
|
- // 根据points创建一个新的数据源和要素数组,
|
|
|
- const vectorSource = new SourceVector({
|
|
|
- features
|
|
|
- })
|
|
|
-
|
|
|
+ vectorSource.addFeature(feature)
|
|
|
+ } else {
|
|
|
+ const features = points.map(([x, y, RtspMain, id]) => {
|
|
|
+ // ol.proj.fromLonLat用于将经纬度坐标从 WGS84 坐标系转换为地图投影坐标系
|
|
|
+ const feature = new Feature({
|
|
|
+ geometry: new Point(fromLonLat([x, y])),
|
|
|
+ custom: {
|
|
|
+ ...custom,
|
|
|
+ id,
|
|
|
+ RtspMain
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return feature
|
|
|
+ })
|
|
|
+ vectorSource.addFeatures(features)
|
|
|
+ }
|
|
|
// 根据点位创建聚合资源
|
|
|
const clusterSource = new Cluster({
|
|
|
distance: currentDis.value, // 设置多少像素以内的点位进行聚合
|
|
|
@@ -309,6 +323,7 @@
|
|
|
// 将矢量图层添加到地图上
|
|
|
map.value.addLayer(clusters)
|
|
|
// sv.setZIndex(zindex) // 设置层级
|
|
|
+
|
|
|
return clusters
|
|
|
}
|
|
|
|
|
|
@@ -361,6 +376,13 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ const contextMenu = document.createElement('div')
|
|
|
+ contextMenu.className = 'ol-context-menu'
|
|
|
+ contextMenu.innerHTML = `
|
|
|
+ <div ><div class="py-2 px-4 bg-#2262acb3 hover:bg-#2262ac" data-action="create-point">创建点位</div>
|
|
|
+`
|
|
|
+ contextMenu.style.display = 'none' // 初始隐藏
|
|
|
+
|
|
|
/**
|
|
|
* 在地图上设置一个标注。
|
|
|
*
|
|
|
@@ -449,6 +471,29 @@
|
|
|
return vectorLayer
|
|
|
}
|
|
|
|
|
|
+ let clusters = null
|
|
|
+ const getPoint = () => {
|
|
|
+ API_MR_CAMERA_GET().then((res) => {
|
|
|
+ const points = res.map((item) => toLonLat([item.X, item.Y]).concat([item.RtspMain, item.Id]))
|
|
|
+ clusters = createCluster(points, {})
|
|
|
+ console.log(clusters)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const createOverlay = (map) => {
|
|
|
+ const overlay = new Overlay({
|
|
|
+ element: contextMenu,
|
|
|
+ positioning: 'bottom-left', // 菜单的定位点相对于坐标
|
|
|
+ offset: [0, 0], // 偏移量
|
|
|
+ autoPan: true,
|
|
|
+ autoPanAnimation: {
|
|
|
+ duration: 250
|
|
|
+ }
|
|
|
+ })
|
|
|
+ map.addOverlay(overlay)
|
|
|
+ return overlay
|
|
|
+ }
|
|
|
+
|
|
|
const initMap = () => {
|
|
|
map.value = new Map({
|
|
|
target: 'map',
|
|
|
@@ -466,11 +511,11 @@
|
|
|
})
|
|
|
const vlText = setMark('text', { text: '中华人民共和国' })
|
|
|
const vlImg = []
|
|
|
- const points = createPointsByRange(100)
|
|
|
// mapData.value.forEach((item) => {
|
|
|
// vlImg.push(setMark('img', { src: videoIcon, ...item }, [item.longitude, item.latitude]))
|
|
|
// })
|
|
|
- const clusters = createCluster(points)
|
|
|
+ getPoint()
|
|
|
+ // const clusters = createCluster(points)
|
|
|
// 缩放显示隐藏层级
|
|
|
const zoomChange = function (e) {
|
|
|
var zoom = parseInt(map.value.getView().getZoom()) //获取当前地图的缩放级别
|
|
|
@@ -521,22 +566,83 @@
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
+ let coordinate = null
|
|
|
+ const contextMenuClick = (event) => {
|
|
|
+ const action = event.target.getAttribute('data-action')
|
|
|
+ if (action) {
|
|
|
+ switch (action) {
|
|
|
+ case 'create-point':
|
|
|
+ console.log('创建点位')
|
|
|
+ // 在这里添加创建点位的逻辑
|
|
|
+ modal.create({
|
|
|
+ title: '新建点位',
|
|
|
+ preset: 'card',
|
|
|
+ maskClosable: false,
|
|
|
+ trapFocus: false,
|
|
|
+ style: {
|
|
|
+ marginTop: '10%'
|
|
|
+ },
|
|
|
+ content: () =>
|
|
|
+ h(AddDevice, {
|
|
|
+ intersection: {
|
|
|
+ x: coordinate ? coordinate[0] : 0,
|
|
|
+ y: coordinate ? coordinate[1] : 0,
|
|
|
+ z: 0
|
|
|
+ },
|
|
|
+ onCloseAddTagModal: ({ x, y, z, RtspMain, id }) => {
|
|
|
+ createCluster([toLonLat([x, y])], {
|
|
|
+ RtspMain,
|
|
|
+ id,
|
|
|
+ type: 'add'
|
|
|
+ })
|
|
|
+ modal.destroyAll()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ contextMenu.style.display = 'none' // 隐藏菜单
|
|
|
+ }
|
|
|
+ }
|
|
|
map.value.on('click', (e) => {
|
|
|
+ contextMenu.style.display = 'none'
|
|
|
+ contextMenu.removeEventListener('click', contextMenuClick)
|
|
|
+ console.log(clusters)
|
|
|
+
|
|
|
clusters.getFeatures(e.pixel).then((clickedFeatures) => {
|
|
|
if (clickedFeatures.length) {
|
|
|
// Get clustered Coordinates
|
|
|
const features = clickedFeatures[0].get('features')
|
|
|
- console.log(features)
|
|
|
if (features.length > 1) {
|
|
|
const extent = boundingExtent(features.map((r) => r.getGeometry().getCoordinates()))
|
|
|
map.value.getView().fit(extent, { duration: 1000, padding: [50, 50, 50, 50] })
|
|
|
} else {
|
|
|
console.log('点击了坐标点')
|
|
|
+ useHomeStore.vId = features[0].get('custom').RtspMain
|
|
|
useHomeStore.temp = 'video'
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
+ // 右键添加标记
|
|
|
+ map.value.on('contextmenu', (event) => {
|
|
|
+ console.log(event)
|
|
|
+
|
|
|
+ event.preventDefault() // 阻止默认右键菜单
|
|
|
+ if (!event.pixel) {
|
|
|
+ console.error('点击位置不在地图范围内')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const overlay = createOverlay(map.value)
|
|
|
+ coordinate = event.coordinate
|
|
|
+ overlay.setPosition(coordinate)
|
|
|
+ contextMenu.style.display = 'block'
|
|
|
+ contextMenu.addEventListener('click', contextMenuClick)
|
|
|
+ console.log('右键点击坐标:', coordinate)
|
|
|
+ // setMark('img', { src: videoIcon }, coordinate) // 添加标记,使用图片作为标记
|
|
|
+ })
|
|
|
map.value.getView().on('change:resolution', zoomChange)
|
|
|
zoomChange()
|
|
|
|