8000 Fix/treemap legend filter by xiaoluoHe · Pull Request #2774 · VisActor/VChart · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix/treemap legend filter #2774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@visactor/vchart",
"comment": "fix: fix issue of continuous legend filter in treemap",
"type": "none"
}
],
"packageName": "@visactor/vchart"
}
51 changes: 51 additions & 0 deletions packages/vchart/__tests__/unit/data/hierarchy.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { hierarchyDimensionStatistics } from '../../../src/data/transforms/hierarchy-dimension-statistics';
import { filterHierarchyDataByRange, isHierarchyItem } from '../../../src/util';
import { disk } from '../../data/disk';

describe('hierarchy data statistic test', () => {
Expand All @@ -19,4 +20,54 @@ describe('hierarchy data statistic test', () => {
expect(result.value.max).toEqual(1512668);
expect(result.value.min).toEqual(0);
});

test('test valid hierarchyData', () => {
const isHierarchy = disk.some(d => isHierarchyItem(d));
expect(isHierarchy).toBe(true);
const data = [
{
id: 1,
value: 10
},
{
id: 5,
value: 25
}
];
expect(data.some(d => isHierarchyItem(d))).toBe(false);
});

test('filterHierarchyDataByRange', () => {
const data = [
{
id: 1,
children: [
{
id: 2,
value: 15,
children: [
{
id: 3,
value: 20
}
]
},
{
id: 4,
value: 5
}
]
},
{
id: 5,
value: 25
}
];

const result = filterHierarchyDataByRange(data, 15, 25);
expect(data.some(d => isHierarchyItem(d))).toBe(true);
expect(JSON.stringify(result)).toEqual(
'[{"id":1,"children":[{"id":2,"value":15,"children":[{"id":3,"value":20}]}]},{"id":5,"value":25}]'
);
});
});
3 changes: 2 additions & 1 deletion packages/vchart/src/component/legend/continuous/legend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export class ContinuousLegend<
options: {
selected: () => this._selectedData,
field: () => this._field,
data: () => this._legendData.getLatestData()
data: () => this._legendData.getLatestData(),
isHierarchyData: s.isHierarchyData
},
level: TransformLevel.legendFilter
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { isEmpty, isValidNumber } from '@visactor/vutils';
10000 import { constants } from 'fs';
import { isArray, isEmpty, isValidNumber } from '@visactor/vutils';
import type { ISeries } from '../../../../series/interface';
import type { IContinuousLegendDataMakeOption, IContinuousLegendFilterOption } from './interface';
import { filterHierarchyDataByRange, isHierarchyItem } from '../../../../util';

// 获取数值范围
export const continuousLegendDataMake = (data: Array<ISeries>, op: IContinuousLegendDataMakeOption) => {
Expand Down Expand Up @@ -34,10 +36,13 @@ export const continuousLegendDataMake = (data: Array<ISeries>, op: IContinuousLe

// 连续数据过滤
export const continuousLegendFilter = (data: Array<any>, op: IContinuousLegendFilterOption) => {
const { selected, field, data: legendData } = op;
const { selected, field, data: legendData, isHierarchyData } = op;
const selectedRange = selected();
const datumField = field();
const dataRange = legendData();
const isHierarchy = isHierarchyData
? isHierarchyData
: (data: Array<any>) => data && data.some(d => d && isHierarchyItem(d));

// 如果数值范围相等,就不进行返回 data,不需要进行过滤
if (selectedRange === dataRange) {
Expand All @@ -46,10 +51,13 @@ export const continuousLegendFilter = (data: Array<any>, op: IContinuousLegendFi

if (datumField && !isEmpty(selectedRange)) {
const [min, max] = selectedRange;

return data.filter(datum => {
return datum[datumField] >= min && datum[datumField] <= max;
});
if (isHierarchy(data)) {
return filterHierarchyDataByRange(data, +min, +max);
} else {
return data.filter(datum => {
return datum[datumField] >= min && datum[datumField] <= max;
});
}
}

return data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface IContinuousLegendFilterOption {
selected: () => StringOrNumber[];
field: () => string | undefined;
data: () => StringOrNumber[];
isHierarchyData?: () => boolean;
}
1 change: 1 addition & 0 deletions packages/vchart/src/series/interface/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export interface ISeries extends IModel {
reFilterViewData: () => void;
reTransformViewData: () => void;
fillData: () => void;
isHierarchyData?: () => boolean;

/**
* 常见数据使用问题
Expand Down
4 changes: 4 additions & 0 deletions packages/vchart/src/series/treemap/treemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,10 @@ export class TreemapSeries extends CartesianSeries<any> {
getActiveMarks(): IMark[] {
return [this._nonLeafMark, this._leafMark];
}

isHierarchyData = () => {
return true;
};
}

mixin(TreemapSeries, Drillable);
Expand Down
48 changes: 48 additions & 0 deletions packages/vchart/src/util/hierarchy.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isObject } from '@visactor/vutils';

/**
* 根据Key, 找到对应节点
* @param hierarchyData
Expand Down Expand Up @@ -93,3 +95,49 @@ export const findHierarchyPath = <T>(
dfs(hierarchyData, []);
return result;
};

export function isHierarchyItem(item: Object, valueField = 'value', childrenField = 'children') {
// 检查 item 是否为对象且不为 null
if (!isObject(item)) {
return false;
}

// 检查 item 是否包含 childrenKey 属性且其值为数组
if (item.hasOwnProperty(childrenField)) {
return Array.isArray(item[childrenField]);
}

return false;
}

export function filterHierarchyDataByRange(
data: any[],
minValue: number,
maxValue: number,
valueField = 'value',
childrenField = 'children'
) {
if (!Array.isArray(data)) {
return data;
}

return data
.map(item => {
const newItem = { ...item };
if (Array.isArray(newItem[childrenField])) {
newItem[childrenField] = filterHierarchyDataByRange(
newItem[childrenField],
minValue,
maxValue,
valueField,
childrenField
);
}
return newItem;
})
.filter(
item =>
(+item[valueField] >= minValue && +item[valueField] <= maxValue) ||
(item[childrenField] && item[childrenField].length > 0)
);
}
Loading
0