|
|
|
@ -10,32 +10,33 @@ import { Style } from 'ol/style' |
|
|
|
import { fromLonLat } from 'ol/proj' |
|
|
|
import type { MarkerData, MapProps } from '../types/map.types' |
|
|
|
import { createMarkerStyle, getClusterMarkerData } from '../utils/map.utils' |
|
|
|
|
|
|
|
import { ANIMATION_CONFIG } from '../constants/map.constants' |
|
|
|
export class MarkerService { |
|
|
|
private markerLayer: VectorLayer<VectorSource | Cluster> | null = null |
|
|
|
private currentProps: MapProps | null = null |
|
|
|
private map: Map | null = null |
|
|
|
private markerLayer: VectorLayer<VectorSource | Cluster> | null = null |
|
|
|
private vectorSource: VectorSource |
|
|
|
|
|
|
|
/** |
|
|
|
* 设置地图实例 |
|
|
|
*/ |
|
|
|
setMap(map: Map): void { |
|
|
|
constructor(map: Map) { |
|
|
|
this.map = map |
|
|
|
this.vectorSource = new VectorSource() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 创建标记图层 |
|
|
|
*/ |
|
|
|
createMarkerLayer(props: MapProps, map?: Map): VectorLayer<VectorSource | Cluster> { |
|
|
|
// 保存地图实例
|
|
|
|
if (map) { |
|
|
|
this.map = map |
|
|
|
createMarkerLayer(props: MapProps): VectorLayer<VectorSource | Cluster> { |
|
|
|
console.log('createMarkerLayer') |
|
|
|
if (this.markerLayer) { |
|
|
|
this.map?.removeLayer(this.markerLayer) |
|
|
|
} |
|
|
|
|
|
|
|
// 保存当前props
|
|
|
|
this.currentProps = { ...props } |
|
|
|
|
|
|
|
const source = new VectorSource() |
|
|
|
return this.createMarkerLayerFromProps(props) |
|
|
|
} |
|
|
|
/** |
|
|
|
* 更新标记数据 |
|
|
|
*/ |
|
|
|
updateData(props: MapProps): void { |
|
|
|
this.vectorSource.clear() |
|
|
|
// 添加标记
|
|
|
|
const markers = props.markers || [] |
|
|
|
markers.forEach((marker) => { |
|
|
|
@ -44,56 +45,17 @@ export class MarkerService { |
|
|
|
markerData: marker |
|
|
|
}) |
|
|
|
feature.setStyle(createMarkerStyle(marker)) |
|
|
|
source.addFeature(feature) |
|
|
|
}) |
|
|
|
|
|
|
|
// 检查是否应该强制使用单个marker模式
|
|
|
|
const shouldForceSingleMark = () => { |
|
|
|
if (!props.forceSingleMark || !this.map) return false |
|
|
|
const currentZoom = this.map.getView().getZoom() |
|
|
|
return currentZoom && currentZoom >= props.forceSingleMark |
|
|
|
} |
|
|
|
console.log('shouldForceSingleMark', shouldForceSingleMark()) |
|
|
|
|
|
|
|
// 如果启用聚合且不强制使用单个marker模式
|
|
|
|
if (props.enableCluster && !shouldForceSingleMark()) { |
|
|
|
const clusterSource = new Cluster({ |
|
|
|
source: source, |
|
|
|
distance: Math.max(props.clusterDistance || 40, 10) // 确保最小距离为10像素
|
|
|
|
this.vectorSource.addFeature(feature) |
|
|
|
}) |
|
|
|
|
|
|
|
this.markerLayer = new VectorLayer({ |
|
|
|
source: clusterSource, |
|
|
|
style: (feature) => { |
|
|
|
const features = feature.get('features') |
|
|
|
|
|
|
|
// 确保features存在且不为空
|
|
|
|
if (!features || features.length === 0) { |
|
|
|
return new Style() // 返回空样式,隐藏无效的feature
|
|
|
|
// this.createMarkerLayerFromProps(props)
|
|
|
|
} |
|
|
|
|
|
|
|
if (features.length === 1) { |
|
|
|
// 单个marker
|
|
|
|
const markerData = features[0].get('markerData') |
|
|
|
return markerData ? createMarkerStyle(markerData) : new Style() |
|
|
|
} else { |
|
|
|
// 聚合marker
|
|
|
|
const highestStatus = getClusterMarkerData(features) |
|
|
|
return createMarkerStyle(highestStatus, true, features.length) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
} else { |
|
|
|
this.markerLayer = new VectorLayer({ |
|
|
|
source: source |
|
|
|
}) |
|
|
|
updateLayer(props: MapProps): void { |
|
|
|
if (this.markerLayer) { |
|
|
|
this.map?.removeLayer(this.markerLayer) |
|
|
|
} |
|
|
|
// this.markerLayer = new VectorLayer({
|
|
|
|
// source: source
|
|
|
|
// })
|
|
|
|
return this.markerLayer |
|
|
|
this.createMarkerLayerFromProps(props) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取标记图层 |
|
|
|
*/ |
|
|
|
@ -102,60 +64,30 @@ export class MarkerService { |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 更新标记数据 |
|
|
|
*/ |
|
|
|
updateMarkers(markers: MarkerData[]): void { |
|
|
|
if (!this.currentProps) return |
|
|
|
console.log('updateMarkers', markers) |
|
|
|
|
|
|
|
// 更新props中的markers
|
|
|
|
this.currentProps.markers = markers |
|
|
|
|
|
|
|
console.log('updateMarkers', markers) |
|
|
|
|
|
|
|
// 完全重新创建markerLayer
|
|
|
|
const newLayer = this.createMarkerLayerFromProps(this.currentProps) |
|
|
|
|
|
|
|
// 如果有旧的layer,将其从地图中移除
|
|
|
|
if (this.markerLayer) { |
|
|
|
// 这里需要外部调用来移除旧layer并添加新layer
|
|
|
|
// 我们只负责创建新的layer
|
|
|
|
} |
|
|
|
|
|
|
|
this.markerLayer = newLayer |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 从props创建markerLayer(内部方法) |
|
|
|
*/ |
|
|
|
private createMarkerLayerFromProps(props: MapProps): VectorLayer<VectorSource | Cluster> { |
|
|
|
const source = new VectorSource() |
|
|
|
// 添加标记
|
|
|
|
const markers = props.markers || [] |
|
|
|
markers.forEach((marker) => { |
|
|
|
const feature = new Feature({ |
|
|
|
geometry: new Point(fromLonLat(marker.coordinates)), |
|
|
|
markerData: marker |
|
|
|
}) |
|
|
|
feature.setStyle(createMarkerStyle(marker)) |
|
|
|
source.addFeature(feature) |
|
|
|
}) |
|
|
|
this.updateData(props) |
|
|
|
|
|
|
|
// 检查是否应该强制使用单个marker模式
|
|
|
|
const shouldForceSingleMark = () => { |
|
|
|
if (!props.forceSingleMark || !this.map) return false |
|
|
|
const currentZoom = this.map.getView().getZoom() |
|
|
|
return currentZoom && currentZoom >= props.forceSingleMark |
|
|
|
console.log('currentZoom',currentZoom) |
|
|
|
// return currentZoom && currentZoom >= props.forceSingleMark
|
|
|
|
return currentZoom && currentZoom >= ANIMATION_CONFIG.clusterThreshold |
|
|
|
} |
|
|
|
console.log('createMarkerLayerFromProps shouldForceSingleMark', shouldForceSingleMark()) |
|
|
|
// console.log('createMarkerLayerFromProps shouldForceSingleMark', shouldForceSingleMark())
|
|
|
|
// 如果启用聚合且不强制使用单个marker模式
|
|
|
|
console.log('shouldForceSingleMark()',shouldForceSingleMark()); |
|
|
|
|
|
|
|
if (props.enableCluster && !shouldForceSingleMark()) { |
|
|
|
const clusterSource = new Cluster({ |
|
|
|
source: source, |
|
|
|
distance: Math.max(props.clusterDistance || 40, 10) |
|
|
|
source: this.vectorSource, |
|
|
|
distance: Math.max(props.clusterDistance || 10, 10) |
|
|
|
}) |
|
|
|
|
|
|
|
return new VectorLayer({ |
|
|
|
this.markerLayer = new VectorLayer({ |
|
|
|
source: clusterSource, |
|
|
|
style: (feature) => { |
|
|
|
const features = feature.get('features') |
|
|
|
@ -177,10 +109,16 @@ export class MarkerService { |
|
|
|
} |
|
|
|
}) |
|
|
|
} else { |
|
|
|
return new VectorLayer({ |
|
|
|
source: source |
|
|
|
// console.log('基础marker')
|
|
|
|
|
|
|
|
this.markerLayer = new VectorLayer({ |
|
|
|
source: this.vectorSource |
|
|
|
}) |
|
|
|
} |
|
|
|
this.map?.addLayer(this.markerLayer) |
|
|
|
|
|
|
|
|
|
|
|
return this.markerLayer |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -197,7 +135,7 @@ export class MarkerService { |
|
|
|
*/ |
|
|
|
destroy(): void { |
|
|
|
this.markerLayer = null |
|
|
|
this.currentProps = null |
|
|
|
// this.currentProps = null
|
|
|
|
this.map = null |
|
|
|
} |
|
|
|
} |
|
|
|
|