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

Feat/treemap label #1836

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 4 commits into from
Dec 27, 2023
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
3 changes: 0 additions & 3 deletions packages/vchart/__tests__/unit/chart/treemap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,11 @@ describe('treemap chart test', () => {
const series: TreemapSeries = vchart.getChart().getAllSeries()[0] as TreemapSeries;
const leafMark = series.getMarkInName('leaf');
const nonLeafMark = series.getMarkInName('nonLeaf');
const labelMark = series.getMarkInName('label');

const leafProduct = leafMark?.getProduct();
const labelProduct = labelMark?.getProduct();
const nonLeafProduct = nonLeafMark?.getProduct();

expect(leafProduct?.elements.length).toBe(86); // 叶子图元
expect(labelProduct?.elements.length).toBe(86); // 叶子标签图元
expect(nonLeafProduct?.elements.length).toBe(17); // 非叶子图元
});
});
2 changes: 1 addition & 1 deletion packages/vchart/src/component/label/label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export class Label<T extends IChartSpec = any> extends BaseLabelComponent<T> {
type: MarkTypeEnum.label,
name: `${markName}-label-${index}`
},
{ noSeparateStyle: true }
{ noSeparateStyle: true, a 10000 ttributeContext: series.getMarkAttributeContext() }
) as ILabelMark;
labelMark.setTarget(mark);
info.push({
Expand Down
20 changes: 19 additions & 1 deletion packages/vchart/src/component/label/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export const labelRuleMap = {
line: LineLabel,
area: LineLabel,
rect3d: barLabel,
arc3d: pieLabel
arc3d: pieLabel,
treemap: treemapLabel
};

export function textAttribute(
Expand Down Expand Up @@ -310,6 +311,23 @@ export function stackLabel(labelInfo: ILabelInfo) {
};
}

/**
* treemap 非叶子节点标签配置规则
*/
export function treemapLabel(labelInfo: ILabelInfo) {
const labelSpec = labelInfo.labelSpec;
return {
customLayoutFunc: (labels: LabelItem[]) => {
return labels.map(label => {
const datum = label.data;
const attribute = textAttribute(labelInfo, datum, labelSpec.formatMethod);
return createText({ ...attribute, id: label.id, pickable: false });
});
},
overlap: false
};
}

/**
* line 图元标签
*/
Expand Down
1 change: 0 additions & 1 deletion packages/vchart/src/series/base/base-series-transformer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { IChartSpecInfo } from '../../chart/interface';
import type { ILabelSpec, TransformedLabelSpec } from '../../component/label';
import type { ILabelMark } from '../../mark/label';
import type { IBaseModelSpecTransformerResult } from '../../model/interface';
import { BaseModelSpecTransformer } from '../../model/base-model-transformer';
import type { ISeriesSpec } from '../../typings';
Expand Down
3 changes: 3 additions & 0 deletions packages/vchart/src/series/base/base-series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ export abstract class BaseSeries<T extends ISeriesSpec> extends BaseModel<T> imp
}

protected _markAttributeContext: ISeriesMarkAttributeContext;
getMarkAttributeContext() {
return this._markAttributeContext;
}

constructor(spec: T, options: ISeriesOption) {
super(spec, options);
Expand Down
3 changes: 2 additions & 1 deletion packages/vchart/src/series/interface/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { IPolarAxisHelper } from '../../component/axis/polar/interface';
import type { ISeriesSeriesInfo, ISeriesSpecInfo, ISeriesStackData } from './common';
import type { ISeriesTooltipHelper } from './tooltip-helper';
import type { IInvalidType, Datum, DirectionType, IGroup, StringOrNumber } from '../../typings';
import type { StateValueType } from '../../compile/mark';
import type { ISeriesMarkAttributeContext, StateValueType } from '../../compile/mark';
import type { StatisticOperations } from '../../data/transforms/dimension-statistics';
import type { IGroupMark } from '../../mark/group';
import type { IArcLabelSpec } from '../pie/interface';
Expand Down Expand Up @@ -188,6 +188,7 @@ export interface ISeries extends IModel {
getGroupFields: () => string[];

getSpecInfo: () => ISeriesSpecInfo;
getMarkAttributeContext: () => ISeriesMarkAttributeContext;
}

export interface ICartesianSeries extends ISeries {
Expand Down
14 changes: 14 additions & 0 deletions packages/vchart/src/series/treemap/treemap-transform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { ISeriesSpec } from '../../typings';
import { BaseSeriesSpecTransformer } from '../base';
import { SeriesMarkNameEnum } from '../interface';
import type { ITreemapSeriesSpec, ITreemapSeriesTheme } from './interface';

export class TreemapSeriesSpecTransformer<
T extends ISeriesSpec = Omit<ITreemapSeriesSpec, 'data'>,
K extends ITreemapSeriesTheme = ITreemapSeriesTheme
> extends BaseSeriesSpecTransformer<T, K> {
protected _transformLabelSpec(spec: T): void {
this._addMarkLabelSpec(spec, SeriesMarkNameEnum.nonLeaf, 'nonLeafLabel' as any, 'initNonLeafLabelMarkStyle' as any);
this._addMarkLabelSpec(spec, SeriesMarkNameEnum.leaf);
}
}
101 changes: 34 additions & 67 deletions packages/vchart/src/series/treemap/treemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { AttributeLevel, DEFAULT_DATA_KEY, VGRAMMAR_HOOK_EVENT } from '../../con
import type { IMark } from '../../mark/interface';
import { MarkTypeEnum } from '../../mark/interface/type';
import type { IRectMark } from '../../mark/rect';
import type { ITextMark } from '../../mark/text';
import type { Datum, IRectMarkSpec, ITextMarkSpec } from '../../typings';
import { CartesianSeries } from '../cartesian/cartesian';
import type { SeriesM AE88 arkMap } from '../interface';
Expand All @@ -14,7 +13,7 @@ import { registerDataSetInstanceTransform } from '../../data/register';
import type { ITreemapOpt } from '../../data/transforms/treemap';
import { treemap } from '../../data/transforms/treemap';
import { flatten } from '../../data/transforms/flatten';
import type { IBounds, IBoundsLike } from '@visactor/vutils';
import type { IBounds } from '@visactor/vutils';
import { isValidNumber, Bounds, Matrix, mixin } from '@visactor/vutils';
import type { PanEventParam, ZoomEventParam } from '../../event/interface';
import type { TreemapNodeElement } from '@visactor/vgrammar-hierarchy';
Expand All @@ -31,23 +30,28 @@ import type { IZoomable } from '../../interaction/zoom/zoomable';
import { Zoomable } from '../../interaction/zoom/zoomable';
import type { IDrillable } from '../../interaction/drill/drillable';
import { Drillable } from '../../interaction/drill/drillable';
import { RectMark, registerRectMark } from '../../mark/rect';
import { TextMark, registerTextMark } from '../../mark/text';
import { registerRectMark } from '../../mark/rect';
import { registerTextMark } from '../../mark/text';
import { treemapSeriesMark } from './constant';
import { Factory } from '../../core/factory';
import { registerTreemapAnimation } from './animation';
import { TransformLevel } from '../../data/initialize';
import type { ILabelMark } from '../../mark/label';
import { TreemapSeriesSpecTransformer } from './treemap-transform';

export class TreemapSeries extends CartesianSeries<any> {
static readonly type: string = SeriesTypeEnum.treemap;
type = SeriesTypeEnum.treemap;

static readonly mark: SeriesMarkMap = treemapSeriesMark;

static readonly transformerConstructor = TreemapSeriesSpecTransformer;
readonly transformerConstructor = TreemapSeriesSpecTransformer;

private _leafMark: IRectMark;
private _nonLeafMark: IRectMark;
private _labelMark: ITextMark;
private _nonLeafLabelMark: ITextMark;
private _labelMark: ILabelMark;
private _nonLeafLabelMark: ILabelMark;

protected declare _spec: ITreemapSeriesSpec;

Expand Down Expand Up @@ -77,8 +81,6 @@ export class TreemapSeries extends CartesianSeries<any> {
// range for treemap layout, change while zoom and pan
private _viewBox: IBounds = new Bounds();

private _clickEnable: boolean = true;

private _enableAnimationHook = this.enableMarkAnimation.bind(this);

setAttrFromSpec(): void {
Expand Down Expand Up @@ -271,47 +273,11 @@ export class TreemapSeries extends CartesianSeries<any> {
this._leafMark = leafMark;
this._trigger.registerMark(leafMark);
}

if (this._spec.label?.visible) {
const textMark = this._createMark(TreemapSeries.mark.label, {
skipBeforeLayouted: false
});
if (textMark) {
textMark.setTransform([
{
type: 'filter',
callback: (datum: TreemapNodeElement) => {
return !this._shouldFilterElement(datum, 'leaf');
}
} as TransformSpec
]);
this._labelMark = textMark;
this._trigger.registerMark(textMark);
}
}

if (this._spec.nonLeafLabel?.visible) {
const textMark = this._createMark(TreemapSeries.mark.nonLeafLabel);
if (textMark) {
textMark.setTransform([
{
type: 'filter' as string,
callback: (datum: TreemapNodeElement) => {
return !this._shouldFilterElement(datum, 'nonLeaf');
}
} as TransformSpec
]);
this._nonLeafLabelMark = textMark;
this._trigger.registerMark(textMark);
}
}
}

initMarkStyle() {
this._initLeafMarkStyle();
this._initNonLeafMarkStyle();
this._initLabelMarkStyle();
this._initNonLeafLabelMarkStyle();
}

protected _initLeafMarkStyle() {
Expand Down Expand Up @@ -351,29 +317,21 @@ export class TreemapSeries extends CartesianSeries<any> {
);
}

protected _initLabelMarkStyle() {
if (!this._labelMark) {
initLabelMarkStyle(labelMark: ILabelMark) {
if (!labelMark) {
return;
}
this._labelMark = labelMark;
labelMark.setRule('treemap');
this.setMarkStyle<ITextMarkSpec>(
this._labelMark,
labelMark,
{
visible: (datum, ctx, { element }) => {
const isLeaf = datum.isLeaf;
if (!isLeaf) {
return false;
}
const bounds = element.getBounds() as IBoundsLike;
const { y0, y1 } = datum;
// 只需要判断高度,宽度放不下会由 limit 来处理
return !!bounds && bounds.y1 > y0 && bounds.y2 < y1;
},
x: datum => (datum.x0 + datum.x1) / 2,
y: datum => (datum.y0 + datum.y1) / 2,
text: datum => {
return datum.datum[datum.depth]?.[this.getDimensionField()[0]];
},
limit: (datum: Datum) => {
maxLineWidth: (datum: Datum) => {
return datum.x1 === datum.x0 ? Number.MIN_VALUE : datum.x1 - datum.x0;
}
},
Expand All @@ -382,14 +340,15 @@ export class TreemapSeries extends CartesianSeries<any> {
);
}

protected _initNonLeafLabelMarkStyle() {
if (!this._nonLeafLabelMark) {
protected initNonLeafLabelMarkStyle(labelMark: ILabelMark) {
if (!labelMark) {
return;
}
this._nonLeafLabelMark = labelMark;
labelMark.setRule('treemap');
this.setMarkStyle<ITextMarkSpec>(
this._nonLeafLabelMark,
labelMark,
{
visible: datum => !!datum.labelRect,
x: datum => {
if (datum.labelRect) {
return (datum.labelRect.x0 + datum.labelRect.x1) / 2;
Expand All @@ -405,7 +364,7 @@ export class TreemapSeries extends CartesianSeries<any> {
text: datum => {
return datum.datum[datum.depth]?.[this.getDimensionField()[0]];
},
limit: (datum: any) => {
maxLineWidth: (datum: any) => {
return datum.x1 === datum.x0 ? Number.MIN_VALUE : datum.x1 - datum.x0;
}
},
Expand Down Expand Up @@ -461,10 +420,8 @@ export class TreemapSeries extends CartesianSeries<any> {

protected initTooltip() {
this._tooltipHelper = new TreemapTooltipHelper(this);
this._nonLeafLabelMark && this._tooltipHelper.activeTriggerSet.mark.add(this._nonLeafMark);
this._leafMark && this._tooltipHelper.activeTriggerSet.mark.add(this._leafMark);
this._labelMark && this._tooltipHelper.activeTriggerSet.mark.add(this._labelMark);
this._nonLeafLabelMark && this._tooltipHelper.activeTriggerSet.mark.add(this._nonLeafLabelMark);
this._nonLeafMark && this._tooltipHelper.activeTriggerSet.mark.add(this._nonLeafMark);
}

private _shouldFilterElement(datum: TreemapNodeElement, nodeType: 'leaf' | 'nonLeaf') {
Expand Down Expand Up @@ -527,6 +484,11 @@ export class TreemapSeries extends CartesianSeries<any> {
this.getMarks().forEach(mark => {
mark.getProduct().animate?.enable();
});
[this._labelMark, this._nonLeafLabelMark].forEach(m => {
if (m && m.getComponent()) {
m.getComponent().getProduct().getGroupGraphicItem().enableAnimation();
}
});
// 在所有动画执行之后关闭动画
this.event.off(VGRAMMAR_HOOK_EVENT.AFTER_DO_RENDER, this._enableAnimationHook);
}
Expand All @@ -535,6 +497,11 @@ export class TreemapSeries extends CartesianSeries<any> {
this.getMarks().forEach(mark => {
mark.getProduct().animate?.disable();
});
[this._labelMark, this._nonLeafLabelMark].forEach(m => {
if (m && m.getComponent()) {
m.getComponent().getProduct().getGroupGraphicItem().disableAnimation();
}
});
}

getDefaultShapeType(): string {
Expand All @@ -546,8 +513,8 @@ export class TreemapSeries extends CartesianSeries<any> {
}
}

mixin(TreemapSeries, Zoomable);
mixin(TreemapSeries, Drillable);
mixin(TreemapSeries, Zoomable);

export const registerTreemapSeries = () => {
registerRectMark();
Expand Down
0