diff --git a/common/changes/@visactor/vchart/feat-gauge-clip_2025-04-15-08-24.json b/common/changes/@visactor/vchart/feat-gauge-clip_2025-04-15-08-24.json new file mode 100644 index 0000000000..f7a9817e3b --- /dev/null +++ b/common/changes/@visactor/vchart/feat-gauge-clip_2025-04-15-08-24.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vchart", + "comment": "feat: gauge support clip when mark outof axis. close#3859", + "type": "none" + } + ], + "packageName": "@visactor/vchart" +} \ No newline at end of file diff --git a/docs/assets/option/en/series/circular-progress.md b/docs/assets/option/en/series/circular-progress.md index 48c5d3e5f2..63d19e7f1d 100644 --- a/docs/assets/option/en/series/circular-progress.md +++ b/docs/assets/option/en/series/circular-progress.md @@ -16,6 +16,30 @@ seriesMarks = ['progress', 'track'] ) }} +#${prefix} tickMask(Object) +Tick mode display. Supported since `1.4.0` version. + +##${prefix} angle(number) +Default width of a single tick, angle value. + +##${prefix} offsetAngle(number) +Offset angle of a single tick, angle value. + +##${prefix} forceAlign(boolean) +Whether the primitives under the tick mask are forced to align with the tick edge. + +##${prefix} style(Object) +{{ use: mark-style( +markName = 'area' +) }} + +{{ use: mark-area( +prefix = '##' + ${prefix} +) }} + +#${prefix} clamp(boolean) = false +Supported since `1.13.9` version, whether the out-of-axis range is clipped (except tick mode, because tick mode has its own clipping). + #${prefix} categoryField(string|string[]) Category field, mapped to the radius axis. Can be declared as an array type, internally grouping data according to the declared fields. diff --git a/docs/assets/option/en/series/gauge.md b/docs/assets/option/en/series/gauge.md index e2bcb0b071..4f02ab8358 100644 --- a/docs/assets/option/en/series/gauge.md +++ b/docs/assets/option/en/series/gauge.md @@ -14,6 +14,30 @@ seriesMarks = ['segment'], ) }} +#${prefix} tickMask(Object) +Tick mode display. Supported since `1.4.0` version. + +##${prefix} angle(number) +Default width of a single tick, angle value. + +##${prefix} offsetAngle(number) +Offset angle of a single tick, angle value. + +##${prefix} forceAlign(boolean) +Whether the primitives under the tick mask are forced to align with the tick edge. + +##${prefix} style(Object) +{{ use: mark-style( +markName = 'area' +) }} + +{{ use: mark-area( +prefix = '##' + ${prefix} +) }} + +#${prefix} clamp(boolean) = false +Supported since `1.13.9` version, whether the out-of-axis range is clipped (except tick mode, because tick mode has its own clipping). + #${prefix} padAngle(number) Configure the angle between sectors. diff --git a/docs/assets/option/en/series/linear-progress.md b/docs/assets/option/en/series/linear-progress.md index d79dcf5cc4..280f1e40ea 100644 --- a/docs/assets/option/en/series/linear-progress.md +++ b/docs/assets/option/en/series/linear-progress.md @@ -78,3 +78,6 @@ Background bar style configuration. Progress bar width. In pixel (px) units. + +#${prefix} clamp(boolean) = false +Supported since `1.13.9` version, whether the out-of-axis range is clipped. diff --git a/docs/assets/option/zh/series/circular-progress.md b/docs/assets/option/zh/series/circular-progress.md index 234e9a6a14..c9ee6d0402 100644 --- a/docs/assets/option/zh/series/circular-progress.md +++ b/docs/assets/option/zh/series/circular-progress.md @@ -16,6 +16,30 @@ seriesMarks = ['progress', 'track'] ) }} +#${prefix} tickMask(Object) +tick 模式显示. 自`1.4.0`版本支持。 + +##${prefix} angle(number) +单个 tick 的默认宽度,角度值。 + +##${prefix} offsetAngle(number) +单个 tick 的偏移角度,角度值。 + +##${prefix} forceAlign(boolean) +tick mask 下的图元是否强制和 tick 的边线对齐。 + +##${prefix} style(Object) +{{ use: mark-style( + markName = 'area' +) }} + +{{ use: mark-area( + prefix = '##' + ${prefix} +) }} + +#${prefix} clamp(boolean) = false +自`1.13.9`版本支持,超出轴范围是否被裁剪(除tick模式外, 因为tick模式自带裁剪)。 + #${prefix} categoryField(string|string[]) 类别字段,映射到半径轴。可以声明为数组类型,内部会依次按照声明的字段进行数据分组。 diff --git a/docs/assets/option/zh/series/gauge.md b/docs/assets/option/zh/series/gauge.md index e3216bb164..259d336db5 100644 --- a/docs/assets/option/zh/series/gauge.md +++ b/docs/assets/option/zh/series/gauge.md @@ -14,6 +14,30 @@ seriesMarks = ['segment'], ) }} +#${prefix} tickMask(Object) +tick 模式显示. 自`1.4.0`版本支持。 + +##${prefix} angle(number) +单个 tick 的默认宽度,角度值。 + +##${prefix} offsetAngle(number) +单个 tick 的偏移角度,角度值。 + +##${prefix} forceAlign(boolean) +tick mask 下的图元是否强制和 tick 的边线对齐。 + +##${prefix} style(Object) +{{ use: mark-style( + markName = 'area' +) }} + +{{ use: mark-area( + prefix = '##' + ${prefix} +) }} + +#${prefix} clamp(boolean) = false +自`1.13.9`版本支持,超出轴范围是否被裁剪(除tick模式外, 因为tick模式自带裁剪)。 + #${prefix} padAngle(number) 配置扇区间隔角度。 diff --git a/docs/assets/option/zh/series/linear-progress.md b/docs/assets/option/zh/series/linear-progress.md index 8f1085781d..fc75c99fee 100644 --- a/docs/assets/option/zh/series/linear-progress.md +++ b/docs/assets/option/zh/series/linear-progress.md @@ -78,3 +78,6 @@ 进度条宽度。 以像素值(px)为单位。 + +#${prefix} clamp(boolean) = false +自`1.13.9`版本支持,超出轴范围是否被裁剪。 diff --git a/packages/vchart/src/chart/progress/linear/linear-progress-transformer.ts b/packages/vchart/src/chart/progress/linear/linear-progress-transformer.ts index 5dbe0a5069..4989857b21 100644 --- a/packages/vchart/src/chart/progress/linear/linear-progress-transformer.ts +++ b/packages/vchart/src/chart/progress/linear/linear-progress-transformer.ts @@ -12,7 +12,7 @@ export class LinearProgressChartSpecTransformer< } protected _getDefaultSeriesSpec(spec: T): ILinearProgressChartSpec { - const series = super._getDefaultSeriesSpec(spec, ['bandWidth', 'progress', 'track']); + const series = super._getDefaultSeriesSpec(spec, ['bandWidth', 'progress', 'track', 'clamp']); series.direction = spec.direction ?? 'horizontal'; series.cornerRadius = spec.cornerRadius ?? 0; diff --git a/packages/vchart/src/series/gauge/gauge.ts b/packages/vchart/src/series/gauge/gauge.ts index ce4322b8bd..a29d09ce5f 100644 --- a/packages/vchart/src/series/gauge/gauge.ts +++ b/packages/vchart/src/series/gauge/gauge.ts @@ -17,6 +17,7 @@ import { GaugeSeriesSpecTransformer } from './gauge-transformer'; import { registerArcMark } from '../../mark/arc'; import { registerPolarLinearAxis } from '../../component/axis/polar'; import { AttributeLevel } from '../../constant/attribute'; +import { valueInScaleRange } from '../../util'; export class GaugeSeries extends ProgressLikeSeries { static readonly type: string = SeriesTypeEnum.gauge; @@ -157,19 +158,21 @@ export class GaugeSeries extends protected _getAngleValueStartWithoutMask(datum: Datum) { const startAngle = this._getAngleValueStartWithoutPadAngle(datum); const endAngle = this._getAngleValueEndWithoutPadAngle(datum); - return clamper( + const angle = clamper( startAngle, (startAngle + endAngle) / 2 )(startAngle + (endAngle > startAngle ? 1 : -1) * Math.abs(this._padAngle / 2)); + return this._spec.clamp ? valueInScaleRange(angle, this.angleAxisHelper.getScale(0)) : angle; } protected _getAngleValueEndWithoutMask(datum: Datum) { const startAngle = this._getAngleValueStartWithoutPadAngle(datum); const endAngle = this._getAngleValueEndWithoutPadAngle(datum); - return clamper( + const angle = clamper( endAngle, (startAngle + endAngle) / 2 )(endAngle - (endAngle > startAngle ? 1 : -1) * Math.abs(this._padAngle / 2)); + return this._spec.clamp ? valueInScaleRange(angle, this.angleAxisHelper.getScale(0)) : angle; } protected _getAngleValueStartWithoutPadAngle(datum: Datum) { diff --git a/packages/vchart/src/series/polar/progress-like/interface.ts b/packages/vchart/src/series/polar/progress-like/interface.ts index 625fac4a04..3b7743ed2c 100644 --- a/packages/vchart/src/series/polar/progress-like/interface.ts +++ b/packages/vchart/src/series/polar/progress-like/interface.ts @@ -33,6 +33,13 @@ export interface IProgressLikeSeriesSpec extends IPolarSeriesSpec { * @since 1.4.0 */ tickMask?: Omit, 'state'> & ITickMaskSpec; + + /** + * 超出轴范围是否被裁剪(除tick模式外, 因为tick模式自带裁剪) + * @since 1.13.9 + * @default false + */ + clamp?: boolean; } export interface IProgressLikeSeriesTheme extends IPolarSeriesTheme { diff --git a/packages/vchart/src/series/polar/progress-like/progress-like.ts b/packages/vchart/src/series/polar/progress-like/progress-like.ts index 390ce365cd..fabef6f192 100644 --- a/packages/vchart/src/series/polar/progress-like/progress-like.ts +++ b/packages/vchart/src/series/polar/progress-like/progress-like.ts @@ -92,8 +92,8 @@ export abstract class ProgressLikeSeries exte index >= subTickData.length || originValue > subTickData[index].value - step / 2 ? Math.min(index, subTickData.length - 1) : index > 0 - ? index - 1 - : undefined; + ? index - 1 + : undefined; if (targetIndex !== undefined) { pos = this.angleAxisHelper.dataToPosition([ subTickData[targetIndex].value - step / 2 // 确保占满整个 tick mask @@ -128,8 +128,8 @@ export abstract class ProgressLikeSeries exte index >= subTickData.length || originValue > subTickData[index].value - step / 2 ? Math.min(index, subTickData.length - 1) : index > 0 - ? index - 1 - : undefined; + ? index - 1 + : undefined; let pos: number; if (targetIndex !== undefined) { pos = this.angleAxisHelper.dataToPosition([ @@ -168,7 +168,8 @@ export abstract class ProgressLikeSeries exte return value; } } - return this.angleAxisHelper.dataToPosition([datum[this._angleField[0]]]); + const angle = this.angleAxisHelper.dataToPosition([datum[this._angleField[0]]]); + return this._spec.clamp ? valueInScaleRange(angle, this.angleAxisHelper.getScale(0)) : angle; } getDimensionField(): string[] { @@ -213,12 +214,12 @@ export abstract class ProgressLikeSeries exte clip: true, clipPath: () => { const axis = this._getAngleAxis(); + const { x, y } = this.angleAxisHelper.center(); + const radius = this._computeLayoutRadius(); if (this._isTickMaskVisible(axis)) { const { tickMask } = this._spec; const { angle, offsetAngle, style = {} } = tickMask; const subTickData = this._getAngleAxisSubTickData(axis); - const { x, y } = this.angleAxisHelper.center(); - const radius = this._computeLayoutRadius(); const markStyle = style as any; return subTickData.map(({ value }) => { const pos = this.angleAxisHelper.dataToPosition([value]) + degreeToRadian(offsetAngle); diff --git a/packages/vchart/src/series/progress/linear/interface.ts b/packages/vchart/src/series/progress/linear/interface.ts index 6f8cb463e3..4ed22b8345 100644 --- a/packages/vchart/src/series/progress/linear/interface.ts +++ b/packages/vchart/src/series/progress/linear/interface.ts @@ -39,6 +39,13 @@ export interface ILinearProgressSeriesSpec */ bandWidth?: number; + /** + * 超出轴范围是否被裁剪 + * @since 1.13.9 + * @default false + */ + clamp?: boolean; + /** * 进度条样式 * TODO: 支持百分比作为padding, 类型为string diff --git a/packages/vchart/src/series/progress/linear/linear.ts b/packages/vchart/src/series/progress/linear/linear.ts index ef25c38c29..b45300ea0f 100644 --- a/packages/vchart/src/series/progress/linear/linear.ts +++ b/packages/vchart/src/series/progress/linear/linear.ts @@ -76,7 +76,10 @@ export class LinearProgressSeries< ); }, y1: (datum: Datum) => valueInScaleRange(this.dataToPositionY(datum), this._yAxisHelper?.getScale?.(0)), - y: () => this._yAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }), + y: () => { + const value = this._yAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }); + return this._spec.clamp ? valueInScaleRange(value, this._yAxisHelper?.getScale?.(0)) : value; + }, width: this._spec.bandWidth - leftPadding - rightPadding, cornerRadius: this._spec.cornerRadius, fill: this.getColorAttribute() @@ -101,7 +104,10 @@ export class LinearProgressSeries< ); }, height: this._spec.bandWidth - topPadding - bottomPadding, - x: () => this._xAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }), + x: () => { + const value = this._xAxisHelper?.dataToPosition([0], { bandPosition: this._bandPosition }); + return this._spec.clamp ? valueInScaleRange(value, this._xAxisHelper?.getScale?.(0)) : value; + }, cornerRadius: this._spec.cornerRadius, fill: this.getColorAttribute() },