Skip to content

Commit

Permalink
Merge pull request #2844 from VisActor/revert-2755-refactor/linear-pr…
Browse files Browse the repository at this point in the history
…ogress

Revert "refactor: refactor linear progress"
  • Loading branch information
xile611 authored Jun 24, 2024
2 parents 5229690 + 4a954b8 commit 837c3f5
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('linearProgress chart test', () => {
expect(series.getSpec().animation).toBeFalsy();

// mark
expect(series.getMarks().length).toEqual(3);
expect(series.getMarks().length).toEqual(4);
expect(chart.getRegionsInIndex().length).toEqual(1);
expect(series.getRegion().id).toEqual(chart.getRegionsInIndex()[0].id);
});
Expand Down
11 changes: 8 additions & 3 deletions packages/vchart/__tests__/unit/series/linearProgres.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ describe('[Domain-Series-LinearProgress] LinearProgress Series', () => {
linearProgress.init({});

const marks = linearProgress.getMarks();
expect(marks.length).toEqual(3);
expect(marks.length).toEqual(4);

const backgroundMark = marks[1];
const groupMark = marks[1] as IGroupMark;
expect(groupMark.type).toEqual('group');
expect(groupMark.name).toEqual('group');
expect(groupMark.getMarks().length).toEqual(2);

const backgroundMark = groupMark.getMarks()[0];
expect(backgroundMark.type).toEqual('rect');
expect(backgroundMark.name).toEqual('track');

const progressMark = marks[2];
const progressMark = groupMark.getMarks()[1];
expect(progressMark.type).toEqual('rect');
expect(progressMark.name).toEqual('progress');
});
Expand Down
213 changes: 100 additions & 113 deletions packages/vchart/src/series/progress/linear/linear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ import { CartesianSeries } from '../../cartesian/cartesian';
import type { SeriesMarkMap } from '../../interface';
import { SeriesMarkNameEnum, SeriesTypeEnum } from '../../interface/type';
import type { IRectMark } from '../../../mark/rect';
import type { IGroupMark } from '../../../mark/group';
import { valueInScaleRange } from '../../../util/scale';
import { AttributeLevel } from '../../../constant';
import type { Datum } from '../../../typings';
import type { Datum, Maybe } from '../../../typings';
import { animationConfig, userAnimationConfig } from '../../../animation/utils';
import {
registerLinearProgressAnimation,
type ILinearProgressAnimationParams,
type LinearProgressAppearPreset
} from './animation';
import type { ILinearProgressSeriesSpec } from './interface';
import type { ILinearProgressSeriesSpec, ILinearProgressSeriesTheme } from './interface';
import { LinearProgressSeriesTooltipHelper } from './tooltip-helper';
import type { IStateAnimateSpec } from '../../../animation/spec';
import { registerRectMark } from '../../../mark/rect';
import type { ICustomPath2D } from '@visactor/vrender-core';
import { RectMark, registerRectMark } from '../../../mark/rect';
import { createRect } from '@visactor/vrender-core';
import { linearProgressSeriesMark } from './constant';
import { Factory } from '../../../core/factory';
import { registerFadeInOutAnimation } from '../../../animation/config';
import type { IMark } from '../../../mark/interface';
import { isValid } from '@visactor/vutils';

export class LinearProgressSeries<
T extends ILinearProgressSeriesSpec = ILinearProgressSeriesSpec
Expand All @@ -33,21 +33,38 @@ export class LinearProgressSeries<

private _progressMark: IRectMark | null = null;
private _trackMark: IRectMark | null = null;

private _progressGroupMark: IGroupMark | null = null;

/**
* 为了解决在圆角情况下,在数值较小时,rect绘图效果不好的问题
* 1. trackMark的所有样式设置在groupMark上,定位也依靠这个groupMark
* 2. progressMark长度固定为整个进度条长度,通过x的偏移体现当前进度
*
* 为了解决在配置tooltip时,trackMark设置为GroupMark无法绑定数据的问题,
* 1. 原本的设置为groupMark的trackMark更名为GroupMark。用来保证在clip效果下progressMark小数据值的绘图效果。
* 1. 增加一层设置为rectMark的trackMark,形状大小与GroupMark相同
*
* 为了解决成组
* 给groupMark的path字段赋值为一个rect数组 也就是一个groupMark具有多个以背景条为轮廓的rect的path
* trackMark与progressMark使用绝对定位
*/
initMark(): void {
this._initProgressGroupMark();
this._initTrackMark();
this._initProgressMark();
}

initMarkStyle(): void {
this._initProgressGroupMarkStyle();
this._initTrackMarkStyle();
this._initProgressMarkStyle();
}

private _initProgressMark() {
this._progressMark = this._createMark(LinearProgressSeries.mark.progress, {
isSeriesMark: true,
customShape: this._spec.progress?.customShape ?? this._defaultProgressCustomShape,
parent: this._progressGroupMark,
customShape: this._spec.progress?.customShape,
stateSort: this._spec.progress?.stateSort
}) as IRectMark;
return this._progressMark;
Expand All @@ -57,9 +74,8 @@ export class LinearProgressSeries<
const progressMark = this._progressMark;
if (progressMark) {
if (this._spec.direction === 'vertical') {
const progress = this._spec.progress || {};
const leftPadding = progress.leftPadding ?? 0;
const rightPadding = progress.rightPadding ?? 0;
const leftPadding = this._spec.progress?.leftPadding ?? 0;
const rightPadding = this._spec.progress?.rightPadding ?? 0;

this.setMarkStyle(
progressMark,
Expand All @@ -71,8 +87,8 @@ export class LinearProgressSeries<
leftPadding
);
},
y1: (datum: Datum) => valueInScaleRange(this.dataToPositionY(datum), this._yAxisHelper?.getScale?.(0)),
y: () => this._yAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }),
y: (datum: Datum) => valueInScaleRange(this.dataToPositionY(datum), this._yAxisHelper?.getScale?.(0)),
height: () => this._yAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }),
width: this._spec.bandWidth - leftPadding - rightPadding,
cornerRadius: this._spec.cornerRadius,
fill: this.getColorAttribute()
Expand All @@ -81,14 +97,15 @@ export class LinearProgressSeries<
AttributeLevel.Series
);
} else {
const progress = this._spec.progress || {};
const topPadding = progress.topPadding ?? 0;
const bottomPadding = progress.bottomPadding ?? 0;
const topPadding = this._spec.progress?.topPadding ?? 0;
const bottomPadding = this._spec.progress?.bottomPadding ?? 0;

this.setMarkStyle(
progressMark,
{
x1: (datum: Datum) => valueInScaleRange(this.dataToPositionX(datum), this._xAxisHelper?.getScale?.(0)),
x: (datum: Datum) =>
valueInScaleRange(this.dataToPositionX(datum), this._xAxisHelper?.getScale?.(0)) -
this._xAxisHelper.dataToPosition([1], { bandPosition: this._bandPosition }),
y: (datum: Datum) => {
return (
valueInScaleRange(this.dataToPositionY(datum), this._yAxisHelper?.getScale?.(0)) -
Expand All @@ -97,7 +114,7 @@ export class LinearProgressSeries<
);
},
height: this._spec.bandWidth - topPadding - bottomPadding,
x: () => this._xAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }),
width: () => this._xAxisHelper?.dataToPosition([1], { bandPosition: this._bandPosition }),
cornerRadius: this._spec.cornerRadius,
fill: this.getColorAttribute()
},
Expand All @@ -108,104 +125,9 @@ export class LinearProgressSeries<
}
}

private _defaultProgressCustomShape = (datum: any[], attrs: any, path: ICustomPath2D) => {
const cornerRadius = this._spec.cornerRadius;
const width = isValid(attrs.width) ? attrs.width : attrs.x1 - attrs.x;
const height = isValid(attrs.height) ? attrs.height : attrs.y1 - attrs.y;
const x0 = Math.min(0, width);
const x1 = Math.max(0, width);
const y0 = Math.min(0, height);
const y1 = Math.max(0, height);

if (cornerRadius > 0) {
let realCornerRadius = cornerRadius;

if (this._spec.direction === 'vertical') {
realCornerRadius = Math.min(Math.abs(width / 2), cornerRadius);

if (2 * realCornerRadius > Math.abs(height)) {
const angle = Math.acos((realCornerRadius - Math.abs(height) / 2) / realCornerRadius);

path.moveTo(x0 + realCornerRadius, y0);
path.arc(
x0 + realCornerRadius,
y0 + realCornerRadius,
realCornerRadius,
1.5 * Math.PI,
1.5 * Math.PI - angle,
true
);
path.arc(
x0 + realCornerRadius,
y1 - realCornerRadius,
realCornerRadius,
angle + Math.PI / 2,
Math.PI / 2,
true
);

path.lineTo(x1 - cornerRadius, y1);
path.arc(
x1 - realCornerRadius,
y1 - realCornerRadius,
realCornerRadius,
Math.PI / 2,
Math.PI / 2 - angle,
true
);
path.arc(
x1 - realCornerRadius,
y0 + realCornerRadius,
realCornerRadius,
-Math.PI / 2 + angle,
-Math.PI / 2,
true
);
path.lineTo(x0 + realCornerRadius, y0);

path.closePath();

return path;
}
} else {
realCornerRadius = Math.min(Math.abs(height / 2), cornerRadius);

if (2 * realCornerRadius > Math.abs(width)) {
const angle = Math.acos((realCornerRadius - Math.abs(width) / 2) / realCornerRadius);
path.moveTo(x0, y0 + realCornerRadius);
path.arc(x0 + realCornerRadius, y0 + realCornerRadius, realCornerRadius, Math.PI, Math.PI + angle);
path.arc(x1 - realCornerRadius, y0 + realCornerRadius, realCornerRadius, -angle, 0);
path.lineTo(x1, y1 - realCornerRadius);
path.arc(x1 - realCornerRadius, y1 - realCornerRadius, realCornerRadius, 0, angle);
path.arc(x0 + realCornerRadius, y1 - realCornerRadius, realCornerRadius, Math.PI - angle, Math.PI);
path.closePath();

return path;
}
}

path.moveTo(x0, y0 + realCornerRadius);
path.arc(x0 + realCornerRadius, y0 + realCornerRadius, realCornerRadius, Math.PI, 1.5 * Math.PI);
path.lineTo(x1 - realCornerRadius, y0);
path.arc(x1 - realCornerRadius, y0 + realCornerRadius, realCornerRadius, -Math.PI / 2, 0);
path.lineTo(x1, y1 - realCornerRadius);
path.arc(x1 - realCornerRadius, y1 - realCornerRadius, realCornerRadius, 0, Math.PI / 2);
path.lineTo(x0 + realCornerRadius, y1);
path.arc(x0 + realCornerRadius, y1 - realCornerRadius, realCornerRadius, Math.PI / 2, Math.PI);
path.closePath();
} else {
path.moveTo(x0, y0);
path.lineTo(x1, y0);
path.lineTo(x1, y1);
path.lineTo(x0, y1);
path.closePath();
}

return path;
};

private _initTrackMark() {
this._trackMark = this._createMark(LinearProgressSeries.mark.track, {
parent: this._progressGroupMark,
customShape: this._spec.track?.customShape,
stateSort: this._spec.track?.stateSort
}) as IRectMark;
Expand Down Expand Up @@ -255,6 +177,71 @@ export class LinearProgressSeries<
}
}

private _initProgressGroupMark() {
// FIXME: disable group mark layout to prevent reevaluate after layout end
this._progressGroupMark = this._createMark(LinearProgressSeries.mark.group, {
skipBeforeLayouted: false
}) as IGroupMark;
return this._progressGroupMark;
}

private _initProgressGroupMarkStyle() {
const groupMark = this._progressGroupMark;
groupMark.setZIndex(this.layoutZIndex);
groupMark.created();

this.setMarkStyle(
groupMark,
{
clip: true,
x: 0,
y: 0,
path: () => {
const rectPaths: any[] = [];
this._rawData?.rawData.forEach((datum: any, index: number) => {
if (this._spec.direction === 'vertical') {
const x =
valueInScaleRange(this.dataToPositionX(datum), this._xAxisHelper?.getScale?.(0)) -
this._spec.bandWidth / 2;
const height = this._scaleY.range()[0];

rectPaths.push(
createRect({
x: x,
y: 0,
height: height,
width: this._spec.bandWidth,
cornerRadius: this._spec.cornerRadius,
fill: true
})
);
} else {
const y =
valueInScaleRange(this.dataToPositionY(datum), this._yAxisHelper?.getScale?.(0)) -
this._spec.bandWidth / 2;
const width = this._scaleX.range()[1];

rectPaths.push(
createRect({
x: 0,
y: y,
height: this._spec.bandWidth,
width: width,
cornerRadius: this._spec.cornerRadius,
fill: true
})
);
}
});
return rectPaths;
}
},
'normal',
AttributeLevel.Series
);
this._progressGroupMark.setInteractive(false);
}

initInteraction(): void {
const marks: IMark[] = [];

Expand Down

0 comments on commit 837c3f5

Please sign in to comment.