diff --git a/common/changes/@visactor/vchart/feat-histogram-bar-padding_2025-05-28-12-01.json b/common/changes/@visactor/vchart/feat-histogram-bar-padding_2025-05-28-12-01.json new file mode 100644 index 0000000000..a1f0441080 --- /dev/null +++ b/common/changes/@visactor/vchart/feat-histogram-bar-padding_2025-05-28-12-01.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vchart", + "comment": "feat: add `barGap` option for histogram chart", + "type": "none" + } + ], + "packageName": "@visactor/vchart" +} \ No newline at end of file diff --git a/docs/assets/option/en/chart/histogram.md b/docs/assets/option/en/chart/histogram.md index 338efb802f..9d3468746b 100644 --- a/docs/assets/option/en/chart/histogram.md +++ b/docs/assets/option/en/chart/histogram.md @@ -25,7 +25,13 @@ x2 field. (x field is the left interval field of frequency statistics, x2 field y2 field. (y field is the left interval field of frequency statistics, y2 field is the right interval field of frequency statistics) +## barGap(number) + +Since `1.13.11`, configuring barGap is supported. + +Used to adjust the distance between each column in the histogram and support passing in pixel values. + {{ use: chart-component( axisType = 'cartesian', noBandAxis = true -) }} \ No newline at end of file +) }} diff --git a/docs/assets/option/zh/chart/histogram.md b/docs/assets/option/zh/chart/histogram.md index ac2360b202..674245e3ef 100644 --- a/docs/assets/option/zh/chart/histogram.md +++ b/docs/assets/option/zh/chart/histogram.md @@ -19,14 +19,19 @@ ## x2Field(string|string[]) -x2 字段。(x字段为频率统计左区间字段,x2字段为频率统计右区间字段) +x2 字段。(x 字段为频率统计左区间字段,x2 字段为频率统计右区间字段) ## y2Field(string|string[]) -y2 字段。(y字段为频率统计左区间字段,y2字段为频率统计右区间字段) +y2 字段。(y 字段为频率统计左区间字段,y2 字段为频率统计右区间字段) + +## barGap(number) + +自 `1.13.11` 版本开始,支持 `barGap` 参数。 + +用于调整直方图中每个柱子之间的距离,支持传入像素值。 {{ use: chart-component( axisType = 'cartesian', noBandAxis = true ) }} - diff --git a/packages/vchart/src/chart/histogram/base/histogram-base-transformer.ts b/packages/vchart/src/chart/histogram/base/histogram-base-transformer.ts index 4539a430c9..b4d24b250e 100644 --- a/packages/vchart/src/chart/histogram/base/histogram-base-transformer.ts +++ b/packages/vchart/src/chart/histogram/base/histogram-base-transformer.ts @@ -9,6 +9,6 @@ export class BaseHistogramChartSpecTransformer ex } protected _getDefaultSeriesSpec(spec: T): any { - return super._getDefaultSeriesSpec(spec, ['x2Field', 'y2Field', 'barMinHeight', 'barBackground']); + return super._getDefaultSeriesSpec(spec, ['x2Field', 'y2Field', 'barMinHeight', 'barBackground', 'barGap']); } } diff --git a/packages/vchart/src/series/bar/bar.ts b/packages/vchart/src/series/bar/bar.ts index 4ae9516bf0..be2b32746d 100644 --- a/packages/vchart/src/series/bar/bar.ts +++ b/packages/vchart/src/series/bar/bar.ts @@ -381,6 +381,29 @@ export class BarSeries extends Cartes return this.dataToPositionY1(datum); } + protected _getLinearBarRange = (start: number, end: number) => { + let [x, x1] = [start, end].sort((a, b) => a - b); + const realBarWidth = x1 - x; + if (this._spec.barGap) { + const halfBarGap = this._spec.barGap * 0.5; + const tempX = x + halfBarGap; + const tempX1 = x1 - halfBarGap; + x = tempX; + x1 = tempX1; + } + + const curBarWidth = x1 - x; + const barMinWidth = getActualNumValue(this._spec.barMinWidth || 2, realBarWidth); + if (curBarWidth < barMinWidth) { + const widthDiff = barMinWidth - curBarWidth; + const halfWidthDiff = widthDiff / 2; + x -= halfWidthDiff; + x1 += halfWidthDiff; + } + + return [x, x1]; + }; + protected _getBarXStart = (datum: Datum, scale: IBaseScale, useWholeRange?: boolean) => { if (this._shouldDoPreCalculate()) { this._calculateStackRectPosition(false); @@ -403,6 +426,12 @@ export class BarSeries extends Cartes return valueInScaleRange(this._dataToPosX1(datum), scale, useWholeRange); }; + protected _getLinearBarXRange = (datum: Datum, scale: IBaseScale, useWholeRange?: boolean) => { + const x = valueInScaleRange(this._dataToPosX(datum), scale, useWholeRange); + const x1 = valueInScaleRange(this._dataToPosX1(datum), scale, useWholeRange); + return this._getLinearBarRange(x, x1); + }; + protected _getBarYStart = (datum: Datum, scale: IBaseScale) => { if (this._shouldDoPreCalculate()) { this._calculateStackRectPosition(true); @@ -425,6 +454,12 @@ export class BarSeries extends Cartes return valueInScaleRange(this._dataToPosY1(datum), scale); }; + protected _getLinearBarYRange = (datum: Datum, scale: IBaseScale, useWholeRange?: boolean) => { + const y = valueInScaleRange(this._dataToPosY(datum), scale, useWholeRange); + const y1 = valueInScaleRange(this._dataToPosY1(datum), scale, useWholeRange); + return this._getLinearBarRange(y, y1); + }; + initBandRectMarkStyle() { const xScale = this._xAxisHelper?.getScale?.(0); const yScale = this._yAxisHelper?.getScale?.(0); @@ -543,8 +578,8 @@ export class BarSeries extends Cartes if (this.direction === Direction.horizontal) { const yChannels = isValid(this._fieldY2) ? { - y: (datum: Datum) => valueInScaleRange(this._dataToPosY(datum), yScale, true), - y1: (datum: Datum) => valueInScaleRange(this._dataToPosY1(datum), yScale, true) + y: (datum: Datum) => this._getLinearBarYRange(datum, yScale, true)[0], + y1: (datum: Datum) => this._getLinearBarYRange(datum, yScale, true)[1] } : { y: (datum: Datum) => @@ -575,8 +610,8 @@ export class BarSeries extends Cartes } else { const xChannels = isValid(this._fieldX2) ? { - x: (datum: Datum) => valueInScaleRange(this._dataToPosX(datum), xScale, true), - x1: (datum: Datum) => valueInScaleRange(this._dataToPosX1(datum), xScale, true) + x: (datum: Datum) => this._getLinearBarXRange(datum, xScale, true)[0], + x1: (datum: Datum) => this._getLinearBarXRange(datum, xScale, true)[1] } : { x: (datum: Datum) => diff --git a/packages/vchart/src/series/bar/interface.ts b/packages/vchart/src/series/bar/interface.ts index dc81714184..84c398603e 100644 --- a/packages/vchart/src/series/bar/interface.ts +++ b/packages/vchart/src/series/bar/interface.ts @@ -119,6 +119,11 @@ export interface IBarSeriesSpec * 圆角支持回调配置 @since 1.12.4 */ stackCornerRadius?: number | number[] | IStackCornerRadiusCallback; + + /** + * 柱条间 gap 值 @since 1.13.11 + */ + barGap?: number; } export interface IBarBackgroundSpec {