mirror of https://gitee.com/antv-l7/antv-l7
feat: 自定义图层 - marker&markerLayer - 多个marker节点性能优化 (#1300)
* chore: 新增marker开发demo * style: 增加格式化空格 * marker性能优化 - 缓存计算变量:ignore (#1298) Co-authored-by: linlb <linlb@homeking365.com> * feat: 自定义图层 - marker&markerLayer - markerLayer多节点kmarker性能优化 * feat: 添加demo * feat: 删除冗余代码 Co-authored-by: Dreammy23 <echo.cmy@antgroup.com> Co-authored-by: bolry <909559682@qq.com> Co-authored-by: linlb <linlb@homeking365.com>
This commit is contained in:
parent
6672caaa6d
commit
16b6abc01f
|
@ -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 (
|
||||
<>
|
||||
<h2>400 个节点测试</h2>
|
||||
|
||||
<h4>高德V1</h4>
|
||||
<div id="gaodeV1" style={{ height: '500px', position: 'relative' }} />
|
||||
|
||||
<h4>Mapbox</h4>
|
||||
<div id="mapbox" style={{ height: '500px', position: 'relative' }} />
|
||||
</>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
height: '500px',
|
||||
position: 'relative',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
|
|
@ -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<IMarkerLayerOption>) {
|
||||
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 = [];
|
||||
|
|
|
@ -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<IMarkerOption>) {
|
||||
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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue