|
|
|
@ -1,7 +1,8 @@ |
|
|
|
/** |
|
|
|
* 标记服务类 |
|
|
|
*/ |
|
|
|
import type { Map } from 'ol' |
|
|
|
import { nextTick } from 'vue' |
|
|
|
import type { Map as OpenLayersMap } from 'ol' |
|
|
|
import { Vector as VectorLayer } from 'ol/layer' |
|
|
|
import { Vector as VectorSource, Cluster } from 'ol/source' |
|
|
|
import { Feature } from 'ol' |
|
|
|
@ -17,13 +18,13 @@ import { createMarkerStyle, getClusterMarkerData, getStatusColor } from '../util |
|
|
|
// 防抖
|
|
|
|
import { debounce } from 'lodash-es' |
|
|
|
export class MarkerService { |
|
|
|
private map: Map | null = null |
|
|
|
private map: OpenLayersMap | null = null |
|
|
|
markerLayer: VectorLayer<Cluster> | null = null |
|
|
|
|
|
|
|
private vectorSource: VectorSource |
|
|
|
private animationService: AnimationService | null = null |
|
|
|
|
|
|
|
constructor(map: Map) { |
|
|
|
constructor(map: OpenLayersMap) { |
|
|
|
this.map = map |
|
|
|
this.vectorSource = new VectorSource() |
|
|
|
this.animationService = new AnimationService(map) |
|
|
|
@ -37,14 +38,19 @@ export class MarkerService { |
|
|
|
this.markerLayer?.setVisible(false) |
|
|
|
this.animationService?.hide() |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 更新标记数据 |
|
|
|
*/ |
|
|
|
updateData(markers: MarkerData[]): void { |
|
|
|
async updateData(markers: MarkerData[]) { |
|
|
|
console.time('animationService clear') |
|
|
|
this.animationService?.clear() |
|
|
|
this.vectorSource.clear() |
|
|
|
// debugger
|
|
|
|
console.timeEnd('animationService clear') |
|
|
|
await nextTick() |
|
|
|
console.time('vectorSource clear') |
|
|
|
this.vectorSource.clear(true) |
|
|
|
console.timeEnd('vectorSource clear') |
|
|
|
await nextTick() |
|
|
|
console.time('create features') |
|
|
|
const features: Feature<Point>[] = [] |
|
|
|
markers.forEach((marker) => { |
|
|
|
const feature = new Feature({ |
|
|
|
@ -56,7 +62,12 @@ export class MarkerService { |
|
|
|
feature.setStyle(createMarkerStyle(statusColor)) |
|
|
|
features.push(feature) |
|
|
|
}) |
|
|
|
console.timeEnd('create features') |
|
|
|
await nextTick() |
|
|
|
console.time('add features') |
|
|
|
this.vectorSource.addFeatures(features) |
|
|
|
|
|
|
|
console.timeEnd('add features') |
|
|
|
this.getSinglePointsInView() |
|
|
|
} |
|
|
|
setClusterDistance = debounce(() => { |
|
|
|
@ -72,9 +83,9 @@ export class MarkerService { |
|
|
|
} else if (zoom <= 6) { |
|
|
|
distance = 80 |
|
|
|
} else if (zoom <= 10) { |
|
|
|
distance = 30 |
|
|
|
distance = 50 |
|
|
|
} else if (zoom <= 16) { |
|
|
|
distance = 30 |
|
|
|
distance = 20 |
|
|
|
} else if (zoom <= 17) { |
|
|
|
distance = 10 |
|
|
|
} |
|
|
|
@ -94,7 +105,7 @@ export class MarkerService { |
|
|
|
|
|
|
|
// 获取聚合图层的源
|
|
|
|
const clusterSource = clusterLayer.getSource() |
|
|
|
if (!clusterSource) return |
|
|
|
if (!clusterSource) return |
|
|
|
|
|
|
|
// 获取当前视图范围
|
|
|
|
const view = map.getView() |
|
|
|
@ -105,7 +116,7 @@ export class MarkerService { |
|
|
|
// console.log('featuresInView',featuresInView)
|
|
|
|
featuresInView.forEach((clusterFeature) => { |
|
|
|
// 关键:获取聚合要素中包含的所有原始要素
|
|
|
|
const originalFeatures = clusterFeature.get('features') |
|
|
|
const originalFeatures = clusterFeature.get('features') |
|
|
|
// console.log('originalFeatures',originalFeatures);
|
|
|
|
|
|
|
|
if (originalFeatures && originalFeatures.length === 1) { |
|
|
|
@ -115,7 +126,6 @@ export class MarkerService { |
|
|
|
} |
|
|
|
}) |
|
|
|
this.animationService?.addAll(singlePoints || []) |
|
|
|
|
|
|
|
}, 300) |
|
|
|
|
|
|
|
/** |
|
|
|
@ -142,7 +152,7 @@ export class MarkerService { |
|
|
|
|
|
|
|
// 确保features存在且不为空
|
|
|
|
if (!features || features.length === 0) { |
|
|
|
return new Style() // 返回空样式,隐藏无效的feature
|
|
|
|
return [] // 返回空样式,隐藏无效的feature
|
|
|
|
} |
|
|
|
// console.log('聚合元素', features)
|
|
|
|
|
|
|
|
@ -180,7 +190,8 @@ export class MarkerService { |
|
|
|
destroy(): void { |
|
|
|
this.markerLayer = null |
|
|
|
this.animationService?.destroy() |
|
|
|
|
|
|
|
this.animationService = null |
|
|
|
|
|
|
|
this.map = null |
|
|
|
} |
|
|
|
} |
|
|
|
|