Skip to content
Open
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,11 @@
{
"changes": [
{
"comment": "feat: support function type for `maxRow` / `maxCol` of the discrete legend, evaluated during layout against the legend's allocated rect, so the row / column count can adapt to the available space",
"type": "minor",
"packageName": "@visactor/vchart"
}
],
"packageName": "@visactor/vchart",
"email": "chendaxin.tk@bytedance.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { getLegendAttributes } from '../../../../src/component/legend/discrete/util';

describe('Discrete legend getLegendAttributes maxRow/maxCol', () => {
const rect = { x: 0, y: 0, width: 200, height: 80 };

test('should evaluate function `maxRow` against the layout rect', () => {
const attrs = getLegendAttributes(
{
type: 'discrete',
orient: 'bottom',
id: 'l1',
maxRow: (ctx: any) => Math.floor(ctx.rect.height / 20)
} as any,
rect as any
);

expect(attrs.maxRow).toBe(4);
});

test('should evaluate function `maxCol` and pass rect / orient / id in the context', () => {
let received: any;
const attrs = getLegendAttributes(
{
type: 'discrete',
orient: 'right',
id: 'l2',
maxCol: (ctx: any) => {
received = ctx;
return 3;
}
} as any,
rect as any
);

expect(attrs.maxCol).toBe(3);
expect(received.rect).toBe(rect);
expect(received.orient).toBe('right');
expect(received.id).toBe('l2');
});

test('should keep numeric `maxRow` / `maxCol` unchanged', () => {
const attrs = getLegendAttributes({ type: 'discrete', maxRow: 2, maxCol: 1 } as any, rect as any);

expect(attrs.maxRow).toBe(2);
expect(attrs.maxCol).toBe(1);
});
});
37 changes: 36 additions & 1 deletion packages/vchart/src/component/legend/discrete/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type {
} from '@visactor/vrender-components';
import type { ILegendCommonSpec, NoVisibleMarkStyle } from '../interface';
import type { IFormatMethod, StringOrNumber } from '../../../typings';
import type { ILayoutRect } from '../../../typings/layout';
import type { IOrientType } from '../../../typings/space';
import type { IBaseScale } from '@visactor/vscale';
import type { IGlobalScale } from '../../../scale/interface';
import type { ComponentThemeWithDirection } from '../../interface';
Expand Down Expand Up @@ -193,6 +195,26 @@ export type ILegendScrollbar = {
} & Omit<LegendScrollbarAttributes, 'railStyle' | 'sliderStyle'>;

/** spec */
/**
* The layout context passed to a `maxRow` / `maxCol` callback. The callback is evaluated during
* layout, so the row / column count can be derived from the space actually allocated to the legend.
* @since 2.0.23
*/
export interface IDiscreteLegendArrangeContext {
/** the layout rect allocated to the legend in the current layout */
rect: ILayoutRect;
/** the orient of the legend */
orient?: IOrientType;
/** the id of the legend */
id?: StringOrNumber;
}

/**
* The max row / col count of a discrete legend. Either a fixed number, or a callback that returns a
* number, evaluated during layout against {@link IDiscreteLegendArrangeContext}.
*/
export type DiscreteLegendArrangeCount = number | ((ctx: IDiscreteLegendArrangeContext) => number);

export type IDiscreteLegendSpec = ILegendCommonSpec & {
type?: 'discrete';
/**
Expand Down Expand Up @@ -231,7 +253,20 @@ export type IDiscreteLegendSpec = ILegendCommonSpec & {
* 默认筛选的数据范围
*/
defaultSelected?: string[];
} & Omit<DiscreteLegendAttrs, 'layout' | 'title' | 'items' | 'item' | 'pager'>;
/**
* The maximum number of rows displayed (for horizontal legend). Besides a fixed number, a
* callback `(ctx) => number` is also supported, which is evaluated during layout so the row
* count can adapt to the space allocated to the legend.
* @since 2.0.23
*/
maxRow?: DiscreteLegendArrangeCount;
/**
* The maximum number of columns displayed (for vertical legend). Besides a fixed number, a
* callback `(ctx) => number` is also supported (see {@link maxRow}).
* @since 2.0.23
*/
maxCol?: DiscreteLegendArrangeCount;
} & Omit<DiscreteLegendAttrs, 'layout' | 'title' | 'items' | 'item' | 'pager' | 'maxRow' | 'maxCol'>;

// theme 主题相关配置
export type IDiscreteLegendCommonTheme = Omit<
Expand Down
10 changes: 10 additions & 0 deletions packages/vchart/src/component/legend/discrete/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ export function getLegendAttributes(spec: IDiscreteLegendSpec, rect: ILayoutRect

const attrs: any = restSpec;

// `maxRow` / `maxCol` may be a callback, evaluated here during layout against the legend's
// available `rect` so the row / column count can adapt to the space (e.g. allow more rows on
// a tall-and-narrow legend). The callback receives the layout context and returns a number.
if (typeof attrs.maxRow === 'function') {
attrs.maxRow = attrs.maxRow({ rect, orient, id });
}
if (typeof attrs.maxCol === 'function') {
attrs.maxCol = attrs.maxCol({ rect, orient, id });
}

// transform title
if (title.visible) {
attrs.title = transformLegendTitleAttributes(title);
Expand Down
Loading