diff --git a/packages/composite-layers/__tests__/unit/composite-layers/flow-layer/index.test.ts b/packages/composite-layers/__tests__/unit/composite-layers/flow-layer/index.test.ts index c504b3cd9..2fee9cea3 100644 --- a/packages/composite-layers/__tests__/unit/composite-layers/flow-layer/index.test.ts +++ b/packages/composite-layers/__tests__/unit/composite-layers/flow-layer/index.test.ts @@ -4,6 +4,7 @@ import { FlowDataProviderState, FlowLayerOptions, FlowSource } from '../../../.. import { DefaultScaleType, getColorAttribute, + getOpacityColorAttribute, getSizeAttribute, } from '../../../../src/composite-layers/flow-layer/utils'; @@ -44,6 +45,7 @@ const dataProviderState: FlowDataProviderState = { zoom: 10.68, bounds: [121.489159, 31.053299, 121.779643, 31.279859], }, + enableCluster: true, clusterType: 'HCA', clusterZoomStep: 1, clusterNodeSize: 64, @@ -84,8 +86,8 @@ describe('flow layer', () => { it('data', () => { expect(dataProvider.getClusterLevels(flowSource, dataProviderState).length).toBe(10); - expect(dataProvider.getFilterLocations(flowSource, dataProviderState).length).toBe(7); - expect(dataProvider.getFilterFlows(flowSource, dataProviderState).length).toBe(4); + expect(dataProvider.getViewLocations(flowSource, dataProviderState).length).toBe(7); + expect(dataProvider.getFilterFlows(flowSource, dataProviderState).length).toBe(7); }); it('circle style', () => { @@ -117,5 +119,10 @@ describe('flow layer', () => { domain: [0, 100], }, }); + + const opacityAttribute = getOpacityColorAttribute([0, 100], 100); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + expect(opacityAttribute?.field).toBe('weight'); }); }); diff --git a/packages/composite-layers/package.json b/packages/composite-layers/package.json index af52d1363..9765cd3cc 100644 --- a/packages/composite-layers/package.json +++ b/packages/composite-layers/package.json @@ -1,6 +1,6 @@ { "name": "@antv/l7-composite-layers", - "version": "0.15.2", + "version": "0.15.3", "description": "Composite layer for @antv/l7", "keywords": [ "antv", diff --git a/packages/composite-layers/src/composite-layers/flow-layer/constants.ts b/packages/composite-layers/src/composite-layers/flow-layer/constants.ts index e166b8ecb..e57034599 100644 --- a/packages/composite-layers/src/composite-layers/flow-layer/constants.ts +++ b/packages/composite-layers/src/composite-layers/flow-layer/constants.ts @@ -47,6 +47,7 @@ export const DEFAULT_OPTIONS: FlowLayerOptions = { weight: 'weight', }, }, + enableCluster: true, clusterType: 'HCA', clusterZoomStep: 1, clusterNodeSize: 64, diff --git a/packages/composite-layers/src/composite-layers/flow-layer/data/build-index.ts b/packages/composite-layers/src/composite-layers/flow-layer/data/build-index.ts index eae6635b1..f60ceb24c 100644 --- a/packages/composite-layers/src/composite-layers/flow-layer/data/build-index.ts +++ b/packages/composite-layers/src/composite-layers/flow-layer/data/build-index.ts @@ -83,6 +83,9 @@ export function buildIndex(clusterLevels: ClusterLevel[]) { return targetCluster; } let cluster = clusterIdMap.get(locationId); + if (cluster && cluster.zoom <= zoom) { + return cluster; + } let parentCluster = (cluster?.parentId && clusterIdMap.get(cluster.parentId)) || undefined; while (cluster && parentCluster) { if (cluster.zoom >= zoom && zoom >= parentCluster.zoom) { diff --git a/packages/composite-layers/src/composite-layers/flow-layer/data/cluster/hca.ts b/packages/composite-layers/src/composite-layers/flow-layer/data/cluster/hca.ts index 339bad86e..8067c2a6c 100644 --- a/packages/composite-layers/src/composite-layers/flow-layer/data/cluster/hca.ts +++ b/packages/composite-layers/src/composite-layers/flow-layer/data/cluster/hca.ts @@ -104,7 +104,7 @@ function getNextClusters( * @returns */ export function clusterByHCA(locations: OriginLocation[], state: ClusterState) { - const { minZoom, maxZoom, clusterZoomStep, clusterNodeSize } = state; + const { minZoom, maxZoom, clusterZoomStep, clusterNodeSize, enableCluster } = state; const trees: (ClusterLocationKDBush | undefined)[] = []; let clusters: ClusterLocation[] = locations .map((location) => ({ @@ -118,23 +118,25 @@ export function clusterByHCA(locations: OriginLocation[], state: ClusterState) { .sort((a, b) => a.weight - b.weight); trees[maxZoom + 1] = createKDTree(clusters, clusterNodeSize); - let prevZoom = maxZoom + 1; - for (let zoom = maxZoom; zoom >= minZoom; zoom -= clusterZoomStep) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const newClusters = getNextClusters(clusters, zoom, trees[prevZoom]!, state); - if (newClusters.length === clusters.length) { - trees[zoom] = trees[prevZoom]; - trees[prevZoom] = undefined; - prevZoom = zoom; - } else { - prevZoom = zoom; - clusters = newClusters.sort((a, b) => a.weight - b.weight); - trees[zoom] = createKDTree(clusters, clusterNodeSize); + if (enableCluster) { + let prevZoom = maxZoom + 1; + for (let zoom = maxZoom; zoom >= minZoom; zoom -= clusterZoomStep) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const newClusters = getNextClusters(clusters, zoom, trees[prevZoom]!, state); + if (newClusters.length === clusters.length) { + trees[zoom] = trees[prevZoom]; + trees[prevZoom] = undefined; + prevZoom = zoom; + } else { + prevZoom = zoom; + clusters = newClusters.sort((a, b) => a.weight - b.weight); + trees[zoom] = createKDTree(clusters, clusterNodeSize); + } } - } - if (trees.length === 0) { - return []; + if (trees.length === 0) { + return []; + } } const clusterLevels: ClusterLevel[] = []; diff --git a/packages/composite-layers/src/composite-layers/flow-layer/data/index.ts b/packages/composite-layers/src/composite-layers/flow-layer/data/index.ts index f485d85fe..bafc1d183 100644 --- a/packages/composite-layers/src/composite-layers/flow-layer/data/index.ts +++ b/packages/composite-layers/src/composite-layers/flow-layer/data/index.ts @@ -10,6 +10,7 @@ export class DataProvider extends EventEmitter { public getSourceParser = (source: FlowSource, config: FlowDataProviderState) => source.parser; public getMapZoom = (source: FlowSource, config: FlowDataProviderState) => config.mapStatus.zoom; public getMapBounds = (source: FlowSource, config: FlowDataProviderState) => config.mapStatus.bounds; + public getEnableCluster = (source: FlowSource, config: FlowDataProviderState) => config.enableCluster; public getClusterType = (source: FlowSource, config: FlowDataProviderState) => config.clusterType; public getExtent = (source: FlowSource, config: FlowDataProviderState) => config.clusterExtent; public getNodeSize = (source: FlowSource, config: FlowDataProviderState) => config.clusterNodeSize; @@ -31,6 +32,7 @@ export class DataProvider extends EventEmitter { */ public getClusterOptions = createSelector( this.getClusterType, + this.getEnableCluster, this.getExtent, this.getNodeSize, this.getRadius, @@ -39,6 +41,7 @@ export class DataProvider extends EventEmitter { this.getZoomStep, function ( clusterType, + enableCluster, clusterExtent, clusterNodeSize, clusterRadius, @@ -46,7 +49,16 @@ export class DataProvider extends EventEmitter { maxZoom, clusterZoomStep ): ClusterState { - return { clusterType, clusterExtent, clusterNodeSize, clusterRadius, minZoom, maxZoom, clusterZoomStep }; + return { + clusterType, + enableCluster, + clusterExtent, + clusterNodeSize, + clusterRadius, + minZoom, + maxZoom, + clusterZoomStep, + }; } ); @@ -71,7 +83,7 @@ export class DataProvider extends EventEmitter { /** * 获取当前需要展示的聚合点 */ - public getFilterLocations = createSelector( + public getViewLocations = createSelector( this.getClusterIndex, this.getMapZoom, this.getMapBounds, @@ -109,7 +121,7 @@ export class DataProvider extends EventEmitter { * 获取当前需要展示的聚合线数据 */ public getFilterFlows = createSelector( - this.getFilterLocations, + this.getViewLocations, this.getAggregatedFlows, this.getMaxTopFlowNum, (filterLocations, fullFlows, maxTopFlowNum) => { @@ -128,6 +140,11 @@ export class DataProvider extends EventEmitter { } ); + public getFilterLocations = createSelector(this.getViewLocations, this.getFilterFlows, (locations, flows) => { + const locationIdSet = new Set(flows.map((flow) => [flow.fromId, flow.toId]).flat()); + return locations.filter((location) => locationIdSet.has(location.id)); + }); + /** * 获取当前层级下筛选前的权重区间,用于计算客流线的宽度和颜色深浅 */ diff --git a/packages/composite-layers/src/composite-layers/flow-layer/types/index.ts b/packages/composite-layers/src/composite-layers/flow-layer/types/index.ts index 2aa25d3c3..0e1270d0e 100644 --- a/packages/composite-layers/src/composite-layers/flow-layer/types/index.ts +++ b/packages/composite-layers/src/composite-layers/flow-layer/types/index.ts @@ -6,6 +6,10 @@ import { CompositeLayerOptions } from '../../../core/composite-layer'; export type GetClusterName = (clusterLocation: ClusterLocation, index: number) => Promise | string; export type ClusterOptions = { + /** + * 是否开启聚合 + */ + enableCluster: boolean; /** * 客流点聚合类型 */ diff --git a/packages/composite-layers/src/composite-layers/flow-layer/utils/style.ts b/packages/composite-layers/src/composite-layers/flow-layer/utils/style.ts index 2a04fee5c..b6c7d0936 100644 --- a/packages/composite-layers/src/composite-layers/flow-layer/utils/style.ts +++ b/packages/composite-layers/src/composite-layers/flow-layer/utils/style.ts @@ -74,8 +74,8 @@ export function getLineOffsetsAttribute( value: (fromId, toId) => { const fromCluster = clusterIndex.clusterIdMap.get(fromId); const toCluster = clusterIndex.clusterIdMap.get(toId); - const fromOffset = fromCluster ? sizeScale(fromCluster.weight) : 0; - const toOffset = toCluster ? sizeScale(toCluster.weight) : 0; + const fromOffset = (fromCluster ? sizeScale?.(fromCluster.weight) : 0) ?? 0; + const toOffset = (toCluster ? sizeScale?.(toCluster.weight) : 0) ?? 0; return [fromOffset, toOffset] as [number, number]; }, }; diff --git a/packages/composite-layers/src/version.ts b/packages/composite-layers/src/version.ts index a9fe5d7c8..a1774ca87 100644 --- a/packages/composite-layers/src/version.ts +++ b/packages/composite-layers/src/version.ts @@ -1 +1 @@ -export default '0.15.2'; +export default '0.15.3'; diff --git a/website/docs/api/composite-layers/flow-layer.zh.md b/website/docs/api/composite-layers/flow-layer.zh.md index e6cec36b1..490abb01d 100644 --- a/website/docs/api/composite-layers/flow-layer.zh.md +++ b/website/docs/api/composite-layers/flow-layer.zh.md @@ -376,6 +376,12 @@ order: 4 } ``` +### `options.`enableCluster + +`boolean` optional default: `true` + +是否开启根据 + ### `options.`fadeOpacityEnabled `boolean` optional default: `true`