|
@@ -12,7 +12,6 @@ import L from 'leaflet'
|
|
|
import DestinationIcon from '../images/destinationIcon.png'
|
|
import DestinationIcon from '../images/destinationIcon.png'
|
|
|
import OriginIcon from '../images/originIcon.png'
|
|
import OriginIcon from '../images/originIcon.png'
|
|
|
import TransferIcon from '../images/transferIcon.png'
|
|
import TransferIcon from '../images/transferIcon.png'
|
|
|
-import { onMounted, ref, watch } from 'vue'
|
|
|
|
|
import * as turf from '@turf/turf'
|
|
import * as turf from '@turf/turf'
|
|
|
import { useThemeStore } from '@/stores/modules/theme'
|
|
import { useThemeStore } from '@/stores/modules/theme'
|
|
|
|
|
|
|
@@ -272,8 +271,7 @@ let initialCenter: L.LatLng | null = null
|
|
|
let initialZoomLevel: number | null = null
|
|
let initialZoomLevel: number | null = null
|
|
|
let isFirstRender = true // 标记是否为首次渲染
|
|
let isFirstRender = true // 标记是否为首次渲染
|
|
|
|
|
|
|
|
-let allMarkers = []
|
|
|
|
|
-let visibleMarkers = new Set()
|
|
|
|
|
|
|
+let mirrorMarkers = ref({})
|
|
|
|
|
|
|
|
// 设置中心点之后的东北角和西南角的经纬度对象
|
|
// 设置中心点之后的东北角和西南角的经纬度对象
|
|
|
let latLngBoundsObj = ref({ northEast: { lat: 0, lng: 0 }, southWest: { lat: 0, lng: 0 } })
|
|
let latLngBoundsObj = ref({ northEast: { lat: 0, lng: 0 }, southWest: { lat: 0, lng: 0 } })
|
|
@@ -283,17 +281,19 @@ const setCenterAndZoom = () => {
|
|
|
// 根据标记的位置设置中心点以及缩放级别
|
|
// 根据标记的位置设置中心点以及缩放级别
|
|
|
const bounds = L.latLngBounds(viewData.value)
|
|
const bounds = L.latLngBounds(viewData.value)
|
|
|
map!.fitBounds(bounds, { paddingTopLeft: [20, 70], paddingBottomRight: [0, 0] })
|
|
map!.fitBounds(bounds, { paddingTopLeft: [20, 70], paddingBottomRight: [0, 0] })
|
|
|
- const curLatLon = map.getBounds()
|
|
|
|
|
- latLngBoundsObj.value = {
|
|
|
|
|
- northEast: { lat: curLatLon.getNorth(), lng: curLatLon.getEast() },
|
|
|
|
|
- southWest: { lat: curLatLon.getSouth(), lng: curLatLon.getWest() }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
if (isFirstRender) {
|
|
if (isFirstRender) {
|
|
|
initialCenter = map!.getCenter()
|
|
initialCenter = map!.getCenter()
|
|
|
initialZoomLevel = map!.getZoom()
|
|
initialZoomLevel = map!.getZoom()
|
|
|
isFirstRender = false
|
|
isFirstRender = false
|
|
|
}
|
|
}
|
|
|
|
|
+ // 获取东北角和西南角的经纬度
|
|
|
|
|
+ const curLatLon = map.getBounds()
|
|
|
|
|
+ latLngBoundsObj.value = {
|
|
|
|
|
+ northEast: { lat: curLatLon.getNorth(), lng: curLatLon.getEast() },
|
|
|
|
|
+ southWest: { lat: curLatLon.getSouth(), lng: curLatLon.getWest() }
|
|
|
|
|
+ }
|
|
|
addResetZoomButton(initialCenter!, initialZoomLevel!)
|
|
addResetZoomButton(initialCenter!, initialZoomLevel!)
|
|
|
}, 500)
|
|
}, 500)
|
|
|
}
|
|
}
|
|
@@ -301,31 +301,42 @@ const setCenterAndZoom = () => {
|
|
|
|
|
|
|
|
// 用来记录初始化时默认打开的弹出窗口,以便在地图移动时判断是否需要重新打开弹出窗口
|
|
// 用来记录初始化时默认打开的弹出窗口,以便在地图移动时判断是否需要重新打开弹出窗口
|
|
|
const popupObj = ref({})
|
|
const popupObj = ref({})
|
|
|
|
|
+// 将经纬度格式化为四位小数,防止精度问题
|
|
|
|
|
+const formatLocationNum = (num: string | number) => {
|
|
|
|
|
+ return Number(num).toFixed(4)
|
|
|
|
|
+}
|
|
|
// 判断是否需要打开弹出窗口
|
|
// 判断是否需要打开弹出窗口
|
|
|
const shouldDisplayPopup = (isInit?: boolean) => {
|
|
const shouldDisplayPopup = (isInit?: boolean) => {
|
|
|
- Object.values(allMarkers).forEach((marker) => {
|
|
|
|
|
|
|
+ const allMarkers = {
|
|
|
|
|
+ ...initMarksObj.value,
|
|
|
|
|
+ ...mirrorMarkers.value
|
|
|
|
|
+ }
|
|
|
|
|
+ Object.values(allMarkers).forEach((marker: any) => {
|
|
|
// 创建 LatLngBounds 对象
|
|
// 创建 LatLngBounds 对象
|
|
|
const bounds = L.latLngBounds(latLngBoundsObj.value.southWest, latLngBoundsObj.value.northEast)
|
|
const bounds = L.latLngBounds(latLngBoundsObj.value.southWest, latLngBoundsObj.value.northEast)
|
|
|
const marksLatLng = marker.getLatLng()
|
|
const marksLatLng = marker.getLatLng()
|
|
|
// 检查标记是否在边界内
|
|
// 检查标记是否在边界内
|
|
|
const isInsideBounds = bounds.contains(marksLatLng)
|
|
const isInsideBounds = bounds.contains(marksLatLng)
|
|
|
- if (isInsideBounds) {
|
|
|
|
|
- if (isInit) {
|
|
|
|
|
- popupObj.value[`${marksLatLng.lat},${marksLatLng.lng}`] = true
|
|
|
|
|
-
|
|
|
|
|
|
|
+ const locationKey = `${formatLocationNum(marksLatLng.lat)},${formatLocationNum(marksLatLng.lng)}`
|
|
|
|
|
+ if (!isInsideBounds) return
|
|
|
|
|
+ if (isInit) {
|
|
|
|
|
+ if (!popupObj.value[locationKey]) {
|
|
|
|
|
+ popupObj.value[locationKey] = true
|
|
|
|
|
+ marker.openPopup()
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const popupItem = popupObj.value[locationKey]
|
|
|
|
|
+ // 如果用户没有关闭弹出窗口,则重新打开弹出窗口
|
|
|
|
|
+ if (popupItem) {
|
|
|
marker.openPopup()
|
|
marker.openPopup()
|
|
|
- } else {
|
|
|
|
|
- const popupItem = popupObj.value[`${marksLatLng.lat},${marksLatLng.lng}`]
|
|
|
|
|
- // 如果用户没有关闭弹出窗口,则重新打开弹出窗口
|
|
|
|
|
- if (popupItem) {
|
|
|
|
|
- marker.openPopup()
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 添加标记后更新中心和缩放级别
|
|
|
|
|
|
|
+// 初始标记的位置
|
|
|
|
|
+const initMarksObj = ref({})
|
|
|
|
|
+// 添加标记
|
|
|
const addMarkersToMap = () => {
|
|
const addMarkersToMap = () => {
|
|
|
if (!map) return // 确保地图已经初始化
|
|
if (!map) return // 确保地图已经初始化
|
|
|
|
|
|
|
@@ -350,15 +361,15 @@ const addMarkersToMap = () => {
|
|
|
marker.on('click', () => {
|
|
marker.on('click', () => {
|
|
|
const latLng = marker.getLatLng() // 获取标记的经纬度
|
|
const latLng = marker.getLatLng() // 获取标记的经纬度
|
|
|
const key = `${latLng.lat},${latLng.lng}` // 使用经纬度组合成一个唯一键
|
|
const key = `${latLng.lat},${latLng.lng}` // 使用经纬度组合成一个唯一键
|
|
|
-
|
|
|
|
|
if (key in popupObj.value) {
|
|
if (key in popupObj.value) {
|
|
|
popupObj.value[key] = marker.isPopupOpen() // 直接切换 isPopup 状态
|
|
popupObj.value[key] = marker.isPopupOpen() // 直接切换 isPopup 状态
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- allMarkers[`${position.lat},${position.lng}`] = marker
|
|
|
|
|
|
|
+ initMarksObj.value[`${position.lat},${position.lng}`] = marker
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
- updateVisibleMarkers(true)
|
|
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ updateVisibleMarkers(true)
|
|
|
|
|
+ }, 1000)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 新增轮船当前位置标记
|
|
// 新增轮船当前位置标记
|
|
@@ -437,32 +448,28 @@ const updateVisibleMarkers = (isInit?: boolean) => {
|
|
|
|
|
|
|
|
let x = cc1
|
|
let x = cc1
|
|
|
|
|
|
|
|
- // 移除不再可见的标记
|
|
|
|
|
- visibleMarkers.forEach((marker: any) => {
|
|
|
|
|
- if (!newVisibleMarkers.has(marker)) {
|
|
|
|
|
- map.removeLayer(marker)
|
|
|
|
|
- delete allMarkers[`${marker.getLatLng().lat},${marker._lng},${marker._x}`]
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 移除所有标记
|
|
|
|
|
+ Object.values(mirrorMarkers.value).forEach((marker: any) => {
|
|
|
|
|
+ map.removeLayer(marker)
|
|
|
|
|
+ delete mirrorMarkers.value[`${marker.getLatLng().lat},${marker.getLatLng().lng}`]
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
// 计算当前视图中的标记,包括多地球的情况
|
|
// 计算当前视图中的标记,包括多地球的情况
|
|
|
while (x >= cc1 && x <= cc2 && cc > 0) {
|
|
while (x >= cc1 && x <= cc2 && cc > 0) {
|
|
|
if (x === 0) {
|
|
if (x === 0) {
|
|
|
|
|
+ addShipMarker(x)
|
|
|
x++
|
|
x++
|
|
|
|
|
+ cc--
|
|
|
continue
|
|
continue
|
|
|
}
|
|
}
|
|
|
- Object.values(allMarkers).forEach((marker) => {
|
|
|
|
|
|
|
+ Object.values(initMarksObj.value).forEach((marker: any) => {
|
|
|
const latLng = marker.getLatLng()
|
|
const latLng = marker.getLatLng()
|
|
|
- const key = `${latLng.lat},${latLng.lng},${x}`
|
|
|
|
|
- if (!allMarkers[key]) {
|
|
|
|
|
|
|
+ const key = `${latLng.lat},${latLng.lng + x * 360}`
|
|
|
|
|
+ if (!mirrorMarkers.value[key]) {
|
|
|
const newMarker: any = L.marker([latLng.lat, latLng.lng + x * 360], {
|
|
const newMarker: any = L.marker([latLng.lat, latLng.lng + x * 360], {
|
|
|
icon: marker.options.icon
|
|
icon: marker.options.icon
|
|
|
}).bindPopup(marker.getPopup().getContent(), marker.getPopup().options)
|
|
}).bindPopup(marker.getPopup().getContent(), marker.getPopup().options)
|
|
|
|
|
|
|
|
- newMarker._x = x
|
|
|
|
|
- // 使用原始的经度作为标记的唯一标识
|
|
|
|
|
- newMarker._lng = latLng.lng
|
|
|
|
|
-
|
|
|
|
|
newMarker.on('click', () => {
|
|
newMarker.on('click', () => {
|
|
|
const latLng = newMarker.getLatLng() // 获取标记的经纬度
|
|
const latLng = newMarker.getLatLng() // 获取标记的经纬度
|
|
|
const key = `${latLng.lat},${latLng.lng}` // 使用经纬度组合成一个唯一键
|
|
const key = `${latLng.lat},${latLng.lng}` // 使用经纬度组合成一个唯一键
|
|
@@ -471,10 +478,10 @@ const updateVisibleMarkers = (isInit?: boolean) => {
|
|
|
popupObj.value[key] = newMarker.isPopupOpen() // 直接切换 isPopup 状态
|
|
popupObj.value[key] = newMarker.isPopupOpen() // 直接切换 isPopup 状态
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- allMarkers[key] = newMarker
|
|
|
|
|
|
|
+ mirrorMarkers.value[key] = newMarker
|
|
|
map.addLayer(newMarker)
|
|
map.addLayer(newMarker)
|
|
|
}
|
|
}
|
|
|
- newVisibleMarkers.add(allMarkers[key])
|
|
|
|
|
|
|
+ newVisibleMarkers.add(mirrorMarkers.value[key])
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
addShipMarker(x)
|
|
addShipMarker(x)
|
|
@@ -482,9 +489,6 @@ const updateVisibleMarkers = (isInit?: boolean) => {
|
|
|
x++
|
|
x++
|
|
|
cc--
|
|
cc--
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 更新可见标记集合
|
|
|
|
|
- visibleMarkers = newVisibleMarkers
|
|
|
|
|
shouldDisplayPopup(isInit)
|
|
shouldDisplayPopup(isInit)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -554,15 +558,15 @@ const getMarker = () => {
|
|
|
}
|
|
}
|
|
|
data.rangePoint.splice(0, 1)
|
|
data.rangePoint.splice(0, 1)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
viewData.value = (data?.rangePoint.length > 0 ? data?.rangePoint : data?.point)?.map(
|
|
viewData.value = (data?.rangePoint.length > 0 ? data?.rangePoint : data?.point)?.map(
|
|
|
(item) => {
|
|
(item) => {
|
|
|
- return [Number(item.lat), Number(item.lon || item.lng)]
|
|
|
|
|
|
|
+ return { lat: Number(item.lat), lng: Number(item.lon || item.lng) }
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
|
- setCenterAndZoom()
|
|
|
|
|
- // 请求成功后添加标记,并动态添加重置按钮
|
|
|
|
|
|
|
+ // 请求成功后添加标记
|
|
|
addMarkersToMap()
|
|
addMarkersToMap()
|
|
|
|
|
+ // 设置中心和缩放级别
|
|
|
|
|
+ setCenterAndZoom()
|
|
|
if (data?.dottedLine) {
|
|
if (data?.dottedLine) {
|
|
|
draw_marker(handleData(data.dottedLine), handleData(data.solidLine))
|
|
draw_marker(handleData(data.dottedLine), handleData(data.solidLine))
|
|
|
map.on('moveend', function () {
|
|
map.on('moveend', function () {
|