diff --git a/dev-demos/features/customLayer/marker-layer.md b/dev-demos/features/customLayer/marker-layer.md index f75e2ab09d..ca2355d824 100644 --- a/dev-demos/features/customLayer/marker-layer.md +++ b/dev-demos/features/customLayer/marker-layer.md @@ -14,11 +14,12 @@ export default () => { zoom: 3, }), }); - // addMarkers1(scene); - addMarkers2(scene); + // addMarkers(scene); + testRemoveMarkerLayer(scene); + // testClearMarkerLayer(scene); }, []); - const addMarkers1 = (scene) => { + const addMarkers = (scene) => { fetch( 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', ) @@ -37,29 +38,67 @@ export default () => { }); }; - const addMarkers2 = (scene) => { + // bugfix验证:执行scene.removeMarkerLayer后,缩放图层marker数据还原 + const testRemoveMarkerLayer = (scene) => { fetch( 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', ) .then((res) => res.json()) .then((nodes) => { - const markerLayer = new MarkerLayer({ cluster: true }); - for (let i = 0; i < 1000; i++) { + const markerLayer = new MarkerLayer({ + cluster: true, + }); + for (let i = 0; i < nodes.features.length; i++) { const { coordinates } = nodes.features[i].geometry; - const el = document.createElement('label'); - el.textContent = coordinates[1]; - el.style.background = getColor(coordinates[1]); - el.style.borderColor = getColor(coordinates[1]); - - const marker = new Marker({ - element: el, - }).setLnglat({ + const marker = new Marker().setLnglat({ lng: coordinates[0], lat: coordinates[1], }); markerLayer.addMarker(marker); } scene.addMarkerLayer(markerLayer); + // 3秒后删除图层 + setTimeout(() => { + scene.removeMarkerLayer(markerLayer); + }, 3000); + }); + }; + + // bugfix验证:执行markerLayer.clear后,图层聚合能力失效 + const testClearMarkerLayer = (scene) => { + fetch( + 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', + ) + .then((res) => res.json()) + .then((nodes) => { + const markerLayer = new MarkerLayer({ + cluster: true, + }); + + for (let i = 0; i < nodes.features.length; i++) { + const { coordinates } = nodes.features[i].geometry; + const marker = new Marker().setLnglat({ + lng: coordinates[0], + lat: coordinates[1], + }); + markerLayer.addMarker(marker); + } + scene.addMarkerLayer(markerLayer); + + setTimeout(() => { + if (markerLayer.getMarkers().length > 0) { + markerLayer.clear(); + } + + for (let i = 0; i < 200; i++) { + const { coordinates } = nodes.features[i].geometry; + const marker = new Marker().setLnglat({ + lng: coordinates[0], + lat: coordinates[1], + }); + markerLayer.addMarker(marker); + } + }, 3 * 1000); }); }; diff --git a/packages/component/src/marker-layer.ts b/packages/component/src/marker-layer.ts index 8f7d1f6b11..b8f59a93f7 100644 --- a/packages/component/src/marker-layer.ts +++ b/packages/component/src/marker-layer.ts @@ -29,11 +29,11 @@ interface IPointFeature { properties: any; } export default class MarkerLayer extends EventEmitter { - private markers: IMarker[] = []; + private markers: IMarker[] = []; // 原始的marker列表 private markerLayerOption: IMarkerLayerOption; private clusterIndex: Supercluster; private points: IPointFeature[] = []; - private clusterMarkers: IMarker[] = []; + private clusterMarkers: IMarker[] = []; // 聚合后的marker列表 private mapsService: IMapService; private scene: Container; private zoom: number; @@ -46,6 +46,7 @@ export default class MarkerLayer extends EventEmitter { bindAll(['update'], this); this.zoom = this.markerLayerOption.clusterOption?.zoom || -99; } + public getDefault() { return { cluster: false, @@ -59,6 +60,8 @@ export default class MarkerLayer extends EventEmitter { }, }; } + + // 执行scene.addMarkerLayer时调用 public addTo(scene: Container) { // this.remove(); this.scene = scene; @@ -76,6 +79,7 @@ export default class MarkerLayer extends EventEmitter { return this; } + // 设置容器大小 private setContainerSize() { if (!this.mapsService) return; const container = this.mapsService.getContainer(); @@ -86,10 +90,12 @@ export default class MarkerLayer extends EventEmitter { }; } + // 获取容器尺寸 private getContainerSize() { return this.containerSize; } + // 在图层添加单个marker public addMarker(marker: IMarker) { const cluster = this.markerLayerOption.cluster; marker.getMarkerLayerContainerSize = this.getContainerSize.bind(this); @@ -142,16 +148,20 @@ export default class MarkerLayer extends EventEmitter { }); } + // 返回当下的markers数据,有聚合图时返回聚合的marker列表,否则返回原始maerker列表 public getMarkers() { const cluster = this.markerLayerOption.cluster; return cluster ? this.clusterMarkers : this.markers; } + // 批量添加marker到scene public addMarkers() { this.getMarkers().forEach((marker: IMarker) => { marker.addTo(this.scene); }); } + + // 清除图层里的marker public clear() { this.markers.forEach((marker: IMarker) => { marker.remove(); @@ -159,10 +169,7 @@ export default class MarkerLayer extends EventEmitter { this.clusterMarkers.forEach((clusterMarker: IMarker) => { clusterMarker.remove(); }); - this.mapsService.off('camerachange', this.update); - this.mapsService.off('viewchange', this.update); - this.mapsService.off('camerachange', this.setContainerSize.bind(this)); - this.mapsService.off('viewchange', this.setContainerSize.bind(this)); + this.markers = []; this.points = []; this.clusterMarkers = []; @@ -171,8 +178,13 @@ export default class MarkerLayer extends EventEmitter { public destroy() { this.clear(); this.removeAllListeners(); + this.mapsService.off('camerachange', this.update); + this.mapsService.off('viewchange', this.update); + this.mapsService.off('camerachange', this.setContainerSize.bind(this)); + this.mapsService.off('viewchange', this.setContainerSize.bind(this)); } + // 将marker数据保存在point中 private addPoint(marker: IMarker, id: number) { const { lng, lat } = marker.getLnglat(); const feature: IPointFeature = { @@ -196,8 +208,11 @@ export default class MarkerLayer extends EventEmitter { if (!this.markerLayerOption.cluster) { return; } - const { radius, minZoom = 0, maxZoom } = this.markerLayerOption - .clusterOption as IMarkerStyleOption; + const { + radius, + minZoom = 0, + maxZoom, + } = this.markerLayerOption.clusterOption; this.clusterIndex = new Supercluster({ radius, minZoom, @@ -217,7 +232,7 @@ export default class MarkerLayer extends EventEmitter { clusterPoint.forEach((feature: any) => { const { field, method } = this.markerLayerOption.clusterOption; // 处理聚合数据 - if (feature.properties && feature.properties?.cluster_id) { + if (feature.properties?.cluster_id) { const clusterData = this.getLeaves(feature.properties?.cluster_id); feature.properties.clusterData = clusterData; if (field && method) { @@ -238,6 +253,7 @@ export default class MarkerLayer extends EventEmitter { marker.addTo(this.scene); }); } + private getLeaves( clusterId: number, limit: number = Infinity, @@ -248,6 +264,7 @@ export default class MarkerLayer extends EventEmitter { } return this.clusterIndex.getLeaves(clusterId, limit, offset); } + private clusterMarker(feature: any) { const clusterOption = this.markerLayerOption.clusterOption; @@ -262,17 +279,20 @@ export default class MarkerLayer extends EventEmitter { }); return marker; } + private normalMarker(feature: any) { const marker_id = feature.properties.marker_id; return this.markers[marker_id]; } private update() { - if (!this.mapsService) { - return; - } + if (!this.mapsService) return; + // 当图层中无marker时,无需更新 + if (this.markers.length === 0) return; + const zoom = this.mapsService.getZoom(); const bbox = this.mapsService.getBounds(); + if ( !this.bbox || Math.abs(zoom - this.zoom) >= 1 || diff --git a/packages/core/src/services/component/MarkerService.ts b/packages/core/src/services/component/MarkerService.ts index 4bf9850c76..4f21668b99 100644 --- a/packages/core/src/services/component/MarkerService.ts +++ b/packages/core/src/services/component/MarkerService.ts @@ -2,11 +2,7 @@ import { Container, injectable } from 'inversify'; import 'reflect-metadata'; import { TYPES } from '../../types'; import { IMapService } from '../map/IMapService'; -import { - IMarker, - IMarkerLayer, - IMarkerService, -} from './IMarkerService'; +import { IMarker, IMarkerLayer, IMarkerService } from './IMarkerService'; @injectable() export default class MarkerService implements IMarkerService {