diff --git a/dev-demos/features/customLayer/marker-layer.md b/dev-demos/features/customLayer/marker-layer.md index ecc11b2eb9..2d187e055b 100644 --- a/dev-demos/features/customLayer/marker-layer.md +++ b/dev-demos/features/customLayer/marker-layer.md @@ -1,40 +1,43 @@ -### markerLayer +### marker-layer ```tsx import { Marker, MarkerLayer, Scene } from '@antv/l7'; -import { GaodeMap, GaodeMapV2, Mapbox } from '@antv/l7-maps'; +import { GaodeMap } from '@antv/l7-maps'; import React, { useEffect } from 'react'; export default () => { useEffect(() => { - const gaodeV1Scene = new Scene({ - id: 'gaodeV1', + const scene = new Scene({ + id: 'map', map: new GaodeMap({ center: [105, 30.258134], - zoom: 2, + zoom: 3, }), }); - // const gaodeV2Scene = new Scene({ - // id: 'gaodeV2', - // map: new GaodeMapV2({ - // center: [105, 30.258134], - // zoom: 3, - // }), - // }); - const mapboxScene = new Scene({ - id: 'mapbox', - map: new Mapbox({ - center: [120, 30], - zoom: 2, - }), - }); - - addMarkers(gaodeV1Scene); - // addMarkers(gaodeV2Scene); - addMarkers(mapboxScene); + // addMarkers1(scene); + addMarkers2(scene); }, []); - const addMarkers = (s) => { + const addMarkers1 = (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(); + for (let i = 0; i < 400; i++) { + const { coordinates } = nodes.features[i].geometry; + const marker = new Marker().setLnglat({ + lng: coordinates[0], + lat: coordinates[1], + }); + markerLayer.addMarker(marker); + } + scene.addMarkerLayer(markerLayer); + }); + }; + + const addMarkers2 = (scene) => { fetch( 'https://gw.alipayobjects.com/os/basement_prod/d3564b06-670f-46ea-8edb-842f7010a7c6.json', ) @@ -56,7 +59,7 @@ export default () => { }); markerLayer.addMarker(marker); } - s.addMarkerLayer(markerLayer); + scene.addMarkerLayer(markerLayer); }); }; @@ -89,15 +92,13 @@ export default () => { }; return ( - <> -

400 个节点测试

- -

高德V1

-
- -

Mapbox

-
- +
); }; ``` diff --git a/packages/component/src/marker-layer.ts b/packages/component/src/marker-layer.ts index e07a5cd3e5..a92b3f1865 100644 --- a/packages/component/src/marker-layer.ts +++ b/packages/component/src/marker-layer.ts @@ -1,4 +1,9 @@ -import { IMapService, IMarker, TYPES } from '@antv/l7-core'; +import { + IMapService, + IMarker, + IMarkerContainerAndBounds, + TYPES, +} from '@antv/l7-core'; import { bindAll, boundsContains, @@ -23,7 +28,6 @@ interface IPointFeature { }; properties: any; } - export default class MarkerLayer extends EventEmitter { private markers: IMarker[] = []; private markerLayerOption: IMarkerLayerOption; @@ -34,6 +38,7 @@ export default class MarkerLayer extends EventEmitter { private scene: Container; private zoom: number; private bbox: IBounds; + private containerSize: IMarkerContainerAndBounds; constructor(option?: Partial) { super(); @@ -65,11 +70,30 @@ export default class MarkerLayer extends EventEmitter { this.mapsService.on('camerachange', this.update); // amap1.x 更新事件 this.mapsService.on('viewchange', this.update); // amap2.0 更新事件 } + this.mapsService.on('camerachange', this.setContainerSize.bind(this)); // amap1.x 更新事件 + this.mapsService.on('viewchange', this.setContainerSize.bind(this)); // amap2.0 更新事件 this.addMarkers(); return this; } + + private setContainerSize() { + if (!this.mapsService) return; + const container = this.mapsService.getContainer(); + this.containerSize = { + containerWidth: container?.scrollWidth || 0, + containerHeight: container?.scrollHeight || 0, + bounds: this.mapsService.getBounds(), + }; + } + + private getContainerSize() { + return this.containerSize; + } + public addMarker(marker: IMarker) { const cluster = this.markerLayerOption.cluster; + marker.getMarkerLayerContainerSize = this.getContainerSize.bind(this); + if (cluster) { this.addPoint(marker, this.markers.length); if (this.mapsService) { @@ -136,6 +160,8 @@ export default class MarkerLayer extends EventEmitter { clusterMarker.remove(); }); this.mapsService.off('camerachange', this.update); + this.mapsService.off('camerachange', this.setContainerSize.bind(this)); + this.mapsService.off('viewchange', this.setContainerSize.bind(this)); this.markers = []; this.points=[]; this.clusterMarkers = []; diff --git a/packages/component/src/marker.ts b/packages/component/src/marker.ts index d5301e1a6d..e700e29097 100644 --- a/packages/component/src/marker.ts +++ b/packages/component/src/marker.ts @@ -1,6 +1,7 @@ import { ILngLat, IMapService, + IMarkerContainerAndBounds, IMarkerOption, IPoint, IPopup, @@ -16,7 +17,6 @@ import { } from '@antv/l7-utils'; import { EventEmitter } from 'eventemitter3'; import { Container } from 'inversify'; - // marker 支持 dragger 未完成 export default class Marker extends EventEmitter { private markerOption: IMarkerOption; @@ -27,6 +27,8 @@ export default class Marker extends EventEmitter { private lngLat: ILngLat; private scene: Container; private added: boolean = false; + public getMarkerLayerContainerSize(): IMarkerContainerAndBounds | void {} + constructor(option?: Partial) { super(); this.markerOption = { @@ -219,25 +221,28 @@ export default class Marker extends EventEmitter { } } + private getCurrentContainerSize() { + const container = this.mapsService.getContainer(); + return { + containerHeight: container?.scrollHeight || 0, + containerWidth: container?.scrollWidth || 0, + bounds: this.mapsService.getBounds(), + }; + } private updatePosition() { if (!this.mapsService) { return; } const { element, offsets } = this.markerOption; const { lng, lat } = this.lngLat; - const bounds = this.mapsService.getBounds(); const pos = this.mapsService.lngLatToContainer([lng, lat]); - if (element) { element.style.display = 'block'; element.style.whiteSpace = 'nowrap'; - const container = this.mapsService.getContainer(); - let containerWidth = 0; - let containerHeight = 0; - if (container) { - containerWidth = container.scrollWidth; - containerHeight = container.scrollHeight; - } + const { containerHeight, containerWidth, bounds } = + this.getMarkerLayerContainerSize() || this.getCurrentContainerSize(); + + if (!bounds) return; // 当前可视区域包含跨日界线 if (Math.abs(bounds[0][0]) > 180 || Math.abs(bounds[1][0]) > 180) { if (pos.x > containerWidth) { diff --git a/packages/core/src/services/component/IMarkerService.ts b/packages/core/src/services/component/IMarkerService.ts index 302ebfdfb2..b426bdbf33 100644 --- a/packages/core/src/services/component/IMarkerService.ts +++ b/packages/core/src/services/component/IMarkerService.ts @@ -1,4 +1,4 @@ -import { anchorType } from '@antv/l7-utils'; +import { anchorType, IBounds } from '@antv/l7-utils'; import { Container } from 'inversify'; import { ILngLat, IMapService, IPoint } from '../map/IMapService'; import { IPopup } from './IPopupService'; @@ -19,6 +19,13 @@ export interface IMarkerOption { extData?: any; style?: CSSStyleDeclaration; } + +export interface IMarkerContainerAndBounds { + containerWidth: number; + containerHeight: number; + bounds: IBounds; +} + export interface IMarker { addTo(scene: Container): void; remove(): void; @@ -32,6 +39,7 @@ export interface IMarker { openPopup(): this; closePopup(): this; setElement(el: HTMLElement): this; + getMarkerLayerContainerSize: () => IMarkerContainerAndBounds | void; } export interface IMarkerService { container: HTMLElement;