diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts index 5c4d1ef45a..0078485365 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/bar.ts @@ -40,6 +40,7 @@ import { isSeriesTooltipFormatterShown, isTooltipItemShown, renderGroupedTooltipItems, + ChildSpec, tooltipCss, tooltipMaxHeight, Transform, @@ -50,6 +51,8 @@ import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel' const { t } = useI18n() const DEFAULT_DATA: any[] = [] +const FULL_COLUMN_WIDTH_PADDING = 0.01 +const PERCENTAGE_FULL_COLUMN_WIDTH_PADDING = 0.002 /** * 柱状图 @@ -268,7 +271,7 @@ export class Bar extends G2ChartView { const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title) let tooltipItems = originalItems if (tooltipAttr.seriesTooltipFormatter?.length) { - // 只隐藏明确配置为不展示的字段,避免过期 formatter 漏掉新指标。 + // 只隐藏明确配置为不展示的字段,避免过期 formatter 漏掉新指标 tooltipItems = originalItems.filter(item => isTooltipItemShown(formatterMap, item, 'yAxis') ) @@ -347,7 +350,7 @@ export class Bar extends G2ChartView { colors.push(color ? color : hexColorToRGBA(ele, basicStyle.alpha)) }) } - const scale = { + const scale: Record = { color: { range: colors }, @@ -387,19 +390,17 @@ export class Bar extends G2ChartView { radius: 0 } } - let columnWidthRatio - const _v = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio - if (_v >= 1 && _v <= 100) { - columnWidthRatio = _v / 100.0 - } else if (_v < 1) { - columnWidthRatio = 1 / 100.0 - } else if (_v > 100) { - columnWidthRatio = 1 - } + const columnWidthRatio = this.getColumnWidthRatio(basicStyle) + const columnPadding = this.getColumnPadding(columnWidthRatio) + let transform = children[0].transform if (columnWidthRatio) { + // 100% 时保留极小 band 间距,避免 transpose 条形图贴边 + scale.x.padding = columnPadding + scale.x.paddingInner = columnPadding + transform = this.configDodgePadding(transform, columnPadding) style = { ...style, - columnWidthRatio + columnWidthRatio: this.getStyleColumnWidthRatio(columnPadding) } } return { @@ -408,6 +409,7 @@ export class Bar extends G2ChartView { { ...children[0], scale, + transform, style }, ...children.slice(1) @@ -415,6 +417,49 @@ export class Bar extends G2ChartView { } } + protected getColumnWidthRatio(basicStyle: DeepPartial): number { + // 兼容历史异常配置,保持样式面板 1-100% 的有效范围 + const value = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio + if (value >= 1 && value <= 100) { + return value / 100.0 + } + if (value < 1) { + return 1 / 100.0 + } + return 1 + } + + protected getColumnPadding(columnWidthRatio: number): number { + return Math.max(1 - columnWidthRatio, this.getFullColumnWidthPadding()) + } + + protected getFullColumnWidthPadding(): number { + if (this.name.startsWith('percentage-bar-stack')) { + return PERCENTAGE_FULL_COLUMN_WIDTH_PADDING + } + return FULL_COLUMN_WIDTH_PADDING + } + + protected getStyleColumnWidthRatio(columnPadding: number): number { + return 1 - columnPadding + } + + protected configDodgePadding( + transforms: ChildSpec['transform'], + padding: number + ): ChildSpec['transform'] { + if (!transforms?.length) { + return transforms + } + if (padding > this.getFullColumnWidthPadding()) { + return transforms + } + // dodgeX 会生成 series band,单独控制多指标柱之间的组内间距 + return transforms.map(transform => + transform.type === 'dodgeX' ? { ...transform, padding } : transform + ) + } + protected configLegend(chart: Chart, options: ViewSpec): ViewSpec { const { children } = options return { diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/horizontal-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/horizontal-bar.ts index 9697fbc6de..cae46f9cfd 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/horizontal-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/horizontal-bar.ts @@ -22,7 +22,6 @@ import { setGradientColor } from '@/views/chart/components/js/panel/common/common_antv' import { valueFormatter } from '@/views/chart/components/js/formatter' -import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart' import { defaultsDeep } from 'lodash-es' const { t } = useI18n() @@ -85,19 +84,12 @@ export class HorizontalBar extends Bar { ...(basicStyle.radiusColumnBar !== 'topRoundAngle' && basicStyle.radiusColumnBar !== 'roundAngle' && { radius: 0 }) } as any - let columnWidthRatio: number | undefined - const _v = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio - if (_v >= 1 && _v <= 100) { - columnWidthRatio = _v / 100.0 - } else if (_v < 1) { - columnWidthRatio = 1 / 100.0 - } else if (_v > 100) { - columnWidthRatio = 1 - } + const columnWidthRatio = this.getColumnWidthRatio(basicStyle) + const columnPadding = this.getColumnPadding(columnWidthRatio) if (columnWidthRatio) { style = { ...style, - columnWidthRatio: columnWidthRatio + columnWidthRatio: this.getStyleColumnWidthRatio(columnPadding) } } if ( @@ -110,6 +102,13 @@ export class HorizontalBar extends Bar { paddingInner: 0.01 } } + // 横向条形图同样通过 x band 控制分类宽度,需要同步外层和 dodgeX 组内间距 + children[0].scale.x = { + ...(children[0].scale.x || {}), + padding: columnPadding, + paddingInner: columnPadding + } + children[0].transform = this.configDodgePadding(children[0].transform, columnPadding) children[0].scale.color.range = colors children[0].scale.y.nice = true children[0].style = { ...children[0].style, ...style } diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-bar.ts index ecc51daa18..d400eea31f 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-bar.ts @@ -200,10 +200,8 @@ export class PercentageStackBar extends GroupStackBar { constructor(name = 'percentage-bar-stack') { super(name) - this.intervalOptions.encode = { - ...this.intervalOptions.encode, - series: d => d.group - } + // 百分比堆叠没有分组槽位,移除 series band,避免默认 series padding 放大柱间距 + delete this.intervalOptions.encode.series // 百分比堆叠与普通堆叠保持同向层级,避免 tooltip 顺序和视觉层级相反 this.intervalOptions.transform = [{ type: 'stackY', reverse: true }, { type: 'normalizeY' }] this.axis = [...BAR_AXIS_TYPE, 'extStack'] diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-horizontal-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-horizontal-bar.ts index 10252db05f..d33ab10163 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-horizontal-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/percentage-stack-horizontal-bar.ts @@ -202,10 +202,8 @@ export class PercentageStackBar extends HorizontalStackBar { constructor(name = 'percentage-bar-stack-horizontal') { super(name) - this.intervalOptions.encode = { - ...this.intervalOptions.encode, - series: d => d.group - } + // 百分比堆叠没有分组槽位,移除 series band,避免默认 series padding 放大条间距 + delete this.intervalOptions.encode.series this.intervalOptions.transform = [{ type: 'stackY' }, { type: 'normalizeY' }] this.axis = [...BAR_AXIS_TYPE, 'extStack'] } diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/progress-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/progress-bar.ts index 367435148e..7855011dcb 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/progress-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/progress-bar.ts @@ -21,7 +21,6 @@ import { TOOLTIP_ITEM_TPL, TOOLTIP_TITLE_TPL } from '@/views/chart/components/js/panel/common/common_antv' -import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart' import { valueFormatter } from '@/views/chart/components/js/formatter' import { HorizontalStackBar } from '@/views/chart/components/js/panel/charts/g2/bar/stack-horizontal-bar' @@ -218,18 +217,20 @@ export class ProgressBar extends HorizontalStackBar { const { children } = superOptions children[0].encode.color = color1[0] children[1].encode.color = color1[1] - let barWidthRatio - const _v = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio - if (_v >= 1 && _v <= 100) { - barWidthRatio = _v / 100.0 - } else if (_v < 1) { - barWidthRatio = 1 / 100.0 - } else if (_v > 100) { - barWidthRatio = 1 - } - if (barWidthRatio) { - children[0].style = { ...children[0].style, columnWidthRatio: barWidthRatio } - children[1].style = { ...children[1].style, columnWidthRatio: barWidthRatio } + const columnWidthRatio = this.getColumnWidthRatio(basicStyle) + const columnPadding = this.getColumnPadding(columnWidthRatio) + const styleColumnWidthRatio = this.getStyleColumnWidthRatio(columnPadding) + if (styleColumnWidthRatio) { + children[0].style = { ...children[0].style, columnWidthRatio: styleColumnWidthRatio } + children[1].scale = { + ...children[1].scale, + x: { + ...(children[1].scale?.x || {}), + padding: columnPadding, + paddingInner: columnPadding + } + } + children[1].style = { ...children[1].style, columnWidthRatio: styleColumnWidthRatio } } return superOptions }