fix(图表): 优化调整柱条图的柱宽百分比的宽度度和间距计算逻辑,确保样式一致性

This commit is contained in:
jianneng-fit2cloud
2026-06-02 19:05:13 +08:00
parent 255338be8a
commit 41320f5105
5 changed files with 85 additions and 44 deletions

View File

@@ -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<ViewSpec, G2Column> {
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<ViewSpec, G2Column> {
colors.push(color ? color : hexColorToRGBA(ele, basicStyle.alpha))
})
}
const scale = {
const scale: Record<string, any> = {
color: {
range: colors
},
@@ -387,19 +390,17 @@ export class Bar extends G2ChartView<ViewSpec, G2Column> {
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<ViewSpec, G2Column> {
{
...children[0],
scale,
transform,
style
},
...children.slice(1)
@@ -415,6 +417,49 @@ export class Bar extends G2ChartView<ViewSpec, G2Column> {
}
}
protected getColumnWidthRatio(basicStyle: DeepPartial<ChartBasicStyle>): 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 {

View File

@@ -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 }

View File

@@ -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']

View File

@@ -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']
}

View File

@@ -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
}