From 55e50c08f3275755ff8d557c8836f40e242bbe35 Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Thu, 28 May 2026 11:29:03 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=9F=BA=E7=A1=80=E6=8A=98=E7=BA=BF=E5=9B=BE=E3=80=81?= =?UTF-8?q?=E9=9D=A2=E7=A7=AF=E5=9B=BE=E7=9A=84=E6=8F=90=E7=A4=BA=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E5=9B=BE=E4=BE=8B=E6=98=BE=E7=A4=BA=E9=A1=BA=E5=BA=8F?= =?UTF-8?q?=E4=B8=8E=E6=8C=87=E6=A0=87=E5=AD=97=E6=AE=B5=E8=87=AA=E4=B8=8A?= =?UTF-8?q?=E8=80=8C=E4=B8=8B=E9=A1=BA=E5=BA=8F=E7=BB=9F=E4=B8=80=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E5=A0=86=E5=8F=A0=E6=8A=98=E7=BA=BF=E5=9B=BE?= =?UTF-8?q?=E7=9A=84=E6=98=BE=E7=A4=BA=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/panel/charts/g2/line/area.ts | 19 ++- .../js/panel/charts/g2/line/common.ts | 124 ++++++++++++++++++ .../js/panel/charts/g2/line/line.ts | 12 +- 3 files changed, 148 insertions(+), 7 deletions(-) diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts index 0437bb1596..12910e41aa 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts @@ -15,7 +15,14 @@ import { } from '@/views/chart/components/js/util' import { cloneDeep, defaultsDeep, isEmpty, merge } from 'lodash-es' import { valueFormatter } from '@/views/chart/components/js/formatter' -import { LINE_AXIS_TYPE, LINE_EDITOR_PROPERTY, LINE_EDITOR_PROPERTY_INNER } from './common' +import { + configStackOrderByYAxis, + configYAxisSeriesLegendDomain, + LINE_AXIS_TYPE, + LINE_EDITOR_PROPERTY, + LINE_EDITOR_PROPERTY_INNER, + sortTooltipItemsByYAxis +} from './common' import { useI18n } from '@/hooks/web/useI18n' import { addExtremumText, extremumEvt } from '@/views/chart/components/js/extremumUitl' import { Chart as G2Chart, G2Spec } from '@antv/g2' @@ -501,7 +508,7 @@ export class Area extends G2ChartView { } } defaultsDeep(options, tmpLegend) - return options + return configYAxisSeriesLegendDomain(chart, options) } protected configAssistLine(chart: Chart, options: G2Spec): G2Spec { @@ -616,7 +623,7 @@ export class Area extends G2ChartView { } const result = [] const head = originalItems[0] - tooltipItems.forEach(item => { + sortTooltipItemsByYAxis(chart, tooltipItems).forEach(item => { if (item.value === null || item.value === undefined) { return } @@ -855,6 +862,10 @@ export class StackArea extends Area { return options } + protected configLegend(chart: Chart, options: G2Spec): G2Spec { + return super.configLegend(chart, configStackOrderByYAxis(chart, options)) + } + protected configTooltip(chart: Chart, options: G2Spec): G2Spec { const customAttr: DeepPartial = parseJson(chart.customAttr) const tooltipAttr = customAttr.tooltip @@ -874,7 +885,7 @@ export class StackArea extends Area { render: (e, { title, items }) => { const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title) const result = [] - items.forEach(item => { + sortTooltipItemsByYAxis(chart, items).forEach(item => { if (item.value === null || item.value === undefined) { return } diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/common.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/common.ts index ffc424174c..02435fdd30 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/common.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/common.ts @@ -1,3 +1,5 @@ +import type { G2Spec } from '@antv/g2' + export const LINE_EDITOR_PROPERTY: EditorProperty[] = [ 'background-overall-component', 'border-style', @@ -72,3 +74,125 @@ export const LINE_AXIS_TYPE: AxisType[] = [ 'extLabel', 'extTooltip' ] + +const Y_AXIS_SERIES_ORDER_NOT_FOUND = Number.MAX_SAFE_INTEGER + +/** + * 只有系列来自值轴指标时才按指标顺序处理;有分组/堆叠维度时,系列来自维度值,保留原逻辑 + */ +export const isYAxisSeriesChart = (chart: Chart) => { + return !!chart.yAxis?.length && !chart.xAxisExt?.length && !chart.extStack?.length +} + +/** + * 指标系列在图表数据里的名称来自字段展示名,未设置展示名时使用字段名 + */ +export const getYAxisSeriesName = axis => axis.chartShowName || axis.name + +/** + * 为 legend 生成值轴指标顺序的 color domain,同时保留数据里未匹配到的新系列 + */ +export const getYAxisSeriesDomain = (chart: Chart, data: any[] = []) => { + const domain = [] + chart.yAxis?.forEach(axis => { + const name = getYAxisSeriesName(axis) + if (name && !domain.includes(name)) { + domain.push(name) + } + }) + data.forEach(item => { + if (item.category && !domain.includes(item.category)) { + domain.push(item.category) + } + }) + return domain +} + +/** + * 建立指标 id/显示名到字段下标的映射,供 tooltip 和堆叠层级排序复用 + */ +export const getYAxisOrderMap = (chart: Chart) => { + const orderMap = new Map() + chart.yAxis?.forEach((axis, index) => { + orderMap.set(axis.id, index) + const name = getYAxisSeriesName(axis) + if (name) { + orderMap.set(name, index) + } + }) + return orderMap +} + +/** + * 根据指标字段顺序获取当前系列排序值,未命中时放到最后并保持原相对顺序 + */ +export const getYAxisSeriesOrder = (orderMap: Map, item) => { + return ( + orderMap.get(item.quotaList?.[0]?.id) ?? + orderMap.get(item.category) ?? + Y_AXIS_SERIES_ORDER_NOT_FOUND + ) +} + +/** + * 对 tooltip items 按右侧指标字段自上而下排序 + */ +export const sortTooltipItemsByYAxis = (chart: Chart, items: any[]) => { + if (!isYAxisSeriesChart(chart)) { + return items + } + const orderMap = getYAxisOrderMap(chart) + return items + .map((item, index) => ({ + item, + index, + order: getYAxisSeriesOrder(orderMap, item) + })) + .sort((a, b) => a.order - b.order || a.index - b.index) + .map(({ item }) => item) +} + +/** + * 对 legend 的 color domain 按右侧指标字段自上而下排序,不覆盖已有颜色映射等样式配置 + */ +export const configYAxisSeriesLegendDomain = (chart: Chart, options: G2Spec) => { + if (!isYAxisSeriesChart(chart)) { + return options + } + const domain = getYAxisSeriesDomain(chart, options.data?.value) + if (!domain.length) { + return options + } + const scale = options.scale ?? {} + options.scale = { + ...scale, + color: { + ...(scale.color ?? {}), + domain + } + } + return options +} + +/** + * G2 正值堆叠是从下往上累加,堆叠折线需要反向使用指标下标来实现视觉自上而下对齐 + */ +export const configStackOrderByYAxis = (chart: Chart, options: G2Spec) => { + if (!isYAxisSeriesChart(chart)) { + return options + } + const orderMap = getYAxisOrderMap(chart) + options.transform = (options.transform ?? []).map(transform => { + if (transform.type !== 'stackY') { + return transform + } + return { + ...transform, + orderBy: item => { + const order = getYAxisSeriesOrder(orderMap, item) + return order === Y_AXIS_SERIES_ORDER_NOT_FOUND ? order : -order + } + } + }) + return options +} diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts index 474750717a..235a5a051a 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts @@ -14,7 +14,13 @@ import { } from '@/views/chart/components/js/util' import { cloneDeep, defaultsDeep, isEmpty, merge } from 'lodash-es' import { valueFormatter } from '@/views/chart/components/js/formatter' -import { LINE_AXIS_TYPE, LINE_EDITOR_PROPERTY, LINE_EDITOR_PROPERTY_INNER } from './common' +import { + configYAxisSeriesLegendDomain, + LINE_AXIS_TYPE, + LINE_EDITOR_PROPERTY, + LINE_EDITOR_PROPERTY_INNER, + sortTooltipItemsByYAxis +} from './common' import { useI18n } from '@/hooks/web/useI18n' import { Chart as G2Chart, G2Spec } from '@antv/g2' import { DEFAULT_YAXIS_STYLE } from '@/views/chart/components/editor/util/chart' @@ -566,7 +572,7 @@ export class Line extends G2ChartView { defaultsDeep(options, scaleOpt) } } - return options + return configYAxisSeriesLegendDomain(chart, options) } protected configAssistLine(chart: Chart, options: G2Spec): G2Spec { @@ -683,7 +689,7 @@ export class Line extends G2ChartView { } const result = [] const head = originalItems[0] - tooltipItems.forEach(item => { + sortTooltipItemsByYAxis(chart, tooltipItems).forEach(item => { if (item.value === null || item.value === undefined) { return } From 2b305cf65ed37ddd59d710914c518309b6b6d950 Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Thu, 28 May 2026 12:26:13 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=9F=BA=E7=A1=80=E6=8A=98=E7=BA=BF=E5=9B=BE=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E9=9D=A2=E7=A7=AF=E5=9B=BE=E5=BC=80=E5=90=AF=E6=9C=80?= =?UTF-8?q?=E5=80=BC=E5=AF=BC=E8=87=B4=E8=BE=85=E5=8A=A9=E7=BA=BF=E9=85=8D?= =?UTF-8?q?=E8=89=B2=E4=B8=8D=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/chart/components/js/extremumUitl.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/core-frontend/src/views/chart/components/js/extremumUitl.ts b/core/core-frontend/src/views/chart/components/js/extremumUitl.ts index 5af1e1656c..39d6779eee 100644 --- a/core/core-frontend/src/views/chart/components/js/extremumUitl.ts +++ b/core/core-frontend/src/views/chart/components/js/extremumUitl.ts @@ -40,6 +40,8 @@ const getRgbaColorLastRgba = (rgbaString: string) => { return lastRGBA } +const EXTREMUM_LABEL_MARK_TYPES = ['point', 'interval'] + /** * 判断图表类型是否支持最值标注(极值标签) * @param chart - 图表配置对象 @@ -94,7 +96,7 @@ export const extremumEvt = ( const chartData = options.children ? options.children : [options] // 遍历所有 series,为标签注入 HTML 和样式 chartData - .filter(item => item.labels?.length) + .filter(item => item.labels?.length && EXTREMUM_LABEL_MARK_TYPES.includes(item.type)) .forEach(item => { item.labels.forEach(label => { const oldPosition = label.position || 'top' From ea301232c669a024af99a5b31cf2596cdc1ec805 Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Thu, 28 May 2026 12:43:27 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E5=9F=BA=E7=A1=80=E6=8A=98=E7=BA=BF=E5=9B=BE=E5=AD=90?= =?UTF-8?q?=E7=B1=BB=E5=88=AB=E7=BB=B4=E5=BA=A6=E7=9A=84=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=E4=BC=98=E5=85=88=E7=BA=A7=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/chart/components/editor/drag-item/DimensionItem.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/core-frontend/src/views/chart/components/editor/drag-item/DimensionItem.vue b/core/core-frontend/src/views/chart/components/editor/drag-item/DimensionItem.vue index ded677ab78..95038740d9 100644 --- a/core/core-frontend/src/views/chart/components/editor/drag-item/DimensionItem.vue +++ b/core/core-frontend/src/views/chart/components/editor/drag-item/DimensionItem.vue @@ -206,6 +206,9 @@ const showSort = computed(() => { return !isChartMix || isDimensionType }) const showSortPriority = computed(() => { + if (props.chart.type === 'line' && props.type === 'dimensionExt') { + return false + } if (props.chart.type.includes('chart-mix')) { return false } From 85b50142a72ffbd2d065adddd23bf854de746fcf Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Thu, 28 May 2026 14:15:05 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=9F=BA=E7=A1=80=E3=80=81=E5=A0=86=E5=8F=A0=E6=8A=98?= =?UTF-8?q?=E7=BA=BF=E5=9B=BE=E4=BB=A5=E5=8F=8A=E9=9D=A2=E7=A7=AF=E5=9B=BE?= =?UTF-8?q?=E7=A1=AE=E4=BF=9D=E6=A0=87=E7=AD=BE=E5=9C=A8=E5=9B=BE=E8=A1=A8?= =?UTF-8?q?=E4=B8=AD=E6=B8=85=E6=99=B0=E5=8F=AF=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/chart/components/js/panel/charts/g2/line/area.ts | 2 ++ .../src/views/chart/components/js/panel/charts/g2/line/line.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts index 12910e41aa..6acaf08342 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/area.ts @@ -390,6 +390,7 @@ export class Area extends G2ChartView { lineLineDash, label: xAxis.axisLabel.show, labelFill: xAxis.axisLabel.color, + labelOpacity: 1, labelFillOpacity: 1, labelFontSize: xAxis.axisLabel.fontSize, tick: xAxis.axisLabel.show, @@ -443,6 +444,7 @@ export class Area extends G2ChartView { lineLineDash, label: yAxis.axisLabel.show, labelFill: yAxis.axisLabel.color, + labelOpacity: 1, labelFillOpacity: 1, labelFontSize: yAxis.axisLabel.fontSize, tick: false, diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts index 235a5a051a..69da45002c 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/line/line.ts @@ -374,6 +374,7 @@ export class Line extends G2ChartView { lineLineDash, label: xAxis.axisLabel.show, labelFill: xAxis.axisLabel.color, + labelOpacity: 1, labelFillOpacity: 1, labelFontSize: xAxis.axisLabel.fontSize, grid: xAxis.splitLine.show, @@ -426,6 +427,7 @@ export class Line extends G2ChartView { lineLineDash, label: yAxis.axisLabel.show, labelFill: yAxis.axisLabel.color, + labelOpacity: 1, labelFillOpacity: 1, labelFontSize: yAxis.axisLabel.fontSize, grid: yAxis.splitLine.show, From 886dd972979ed661793b30641559cf21e78ce7e0 Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Thu, 28 May 2026 15:23:29 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=A0=86=E5=8F=A0=E6=9F=B1=E7=8A=B6=E5=9B=BE=E6=80=BB?= =?UTF-8?q?=E8=AE=A1=E6=A0=87=E7=AD=BE=E5=8F=91=E7=94=9F=E9=87=8D=E5=8F=A0?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../js/panel/charts/g2/bar/stack-bar.ts | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-bar.ts index b11ad82d3a..1fd8736f5e 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-bar.ts @@ -75,7 +75,7 @@ export class StackBar extends Bar { fill: labelAttr.color, fontSize: labelAttr.fontSize, ...position, - formatter: (value, _data) => valueFormatter(value, labelAttr.labelFormatter), + formatter: value => valueFormatter(value, labelAttr.labelFormatter), ...transform }) } @@ -83,19 +83,38 @@ export class StackBar extends Bar { if (labelAttr.showTotal) { const formatterCfg = labelAttr.labelFormatter ?? formatterItem const groupedData = groupBy(options.data, 'field') - for (const [key, values] of Object.entries(groupedData)) { + const totalData = Object.entries(groupedData).map(([key, values]) => { const total = values.reduce((a, b) => a + b.value, 0) - const value = valueFormatter(total, formatterCfg) + return { + field: key, + value: total, + totalLabel: valueFormatter(total, formatterCfg) + } + }) + if (totalData.length) { children.push({ - type: 'text', - data: [key, total], - style: { - text: value, - textAlign: 'center', - dy: -10, - fill: labelAttr.color, - fontSize: labelAttr.fontSize + type: 'point', + data: totalData, + encode: { + x: 'field', + y: 'value' }, + style: { + opacity: 0 + }, + labels: [ + { + text: 'totalLabel', + fillOpacity: 1, + fill: labelAttr.color, + fontSize: labelAttr.fontSize, + position: 'top', + dx: 0, + dy: -10, + ...transform, + textAlign: 'center' + } + ], tooltip: false }) } From d67a88e0d946a6be9132eb9a64c33e2668f80a7e Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Thu, 28 May 2026 15:36:55 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix(=E5=9B=BE=E8=A1=A8):=20=E5=A0=86?= =?UTF-8?q?=E5=8F=A0=E6=9D=A1=E5=BD=A2=E5=9B=BE=E6=94=AF=E6=8C=81=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=98=BE=E7=A4=BA=E6=8C=87=E6=A0=87=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E6=80=BB=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../charts/g2/bar/stack-horizontal-bar.ts | 70 ++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-horizontal-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-horizontal-bar.ts index 28065b145c..c5e032fe1a 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-horizontal-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/g2/bar/stack-horizontal-bar.ts @@ -1,4 +1,7 @@ -import { BAR_EDITOR_PROPERTY } from '@/views/chart/components/js/panel/charts/g2/bar/common' +import { + BAR_EDITOR_PROPERTY, + BAR_EDITOR_PROPERTY_INNER +} from '@/views/chart/components/js/panel/charts/g2/bar/common' import { flow, parseJson } from '@/views/chart/components/js/util' import { createTooltipWrapper, @@ -11,9 +14,9 @@ import { TOOLTIP_ITEM_TPL, TOOLTIP_TITLE_TPL } from '@/views/chart/components/js/panel/common/common_antv' -import { valueFormatter } from '@/views/chart/components/js/formatter' +import { formatterItem, valueFormatter } from '@/views/chart/components/js/formatter' import { HorizontalBar } from '@/views/chart/components/js/panel/charts/g2/bar/horizontal-bar' -import { isEmpty } from 'lodash-es' +import { groupBy, isEmpty } from 'lodash-es' const { t } = useI18n() @@ -33,7 +36,15 @@ export class HorizontalStackBar extends HorizontalBar { } propertyInner = { ...this['propertyInner'], - 'label-selector': ['color', 'fontSize', 'hPosition', 'labelFormatter'], + 'label-selector': [ + ...BAR_EDITOR_PROPERTY_INNER['label-selector'], + 'hPosition', + 'showTotal', + 'totalColor', + 'totalFontSize', + 'totalFormatter', + 'showStackQuota' + ], 'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'tooltipFormatter', 'show'] } @@ -53,23 +64,64 @@ export class HorizontalStackBar extends HorizontalBar { ...(labelAttr.fullDisplay ? [] : [{ type: 'overlapHide' }]) ] - const labels = [ - { + const labels = [] + if (labelAttr.showStackQuota ?? true) { + labels.push({ text: 'value', fillOpacity: 1, fill: labelAttr.color, fontSize: labelAttr.fontSize, ...position, - formatter: (value, _data) => { - debugger + formatter: value => { if (value === null || value === undefined) { return '' } return valueFormatter(value, labelAttr.labelFormatter) }, transform + }) + } + + if (labelAttr.showTotal) { + const formatterCfg = labelAttr.labelFormatter ?? formatterItem + const groupedData = groupBy(options.data, 'field') + const totalData = Object.entries(groupedData).map(([key, values]) => { + const total = values.reduce((a, b) => a + b.value, 0) + return { + field: key, + value: total, + totalLabel: valueFormatter(total, formatterCfg) + } + }) + if (totalData.length) { + children.push({ + type: 'point', + data: totalData, + encode: { + x: 'field', + y: 'value' + }, + coordinate: { transform: [{ type: 'transpose' }] }, + style: { + opacity: 0 + }, + labels: [ + { + text: 'totalLabel', + fillOpacity: 1, + fill: labelAttr.color, + fontSize: labelAttr.fontSize, + position: 'right', + dx: 4, + dy: 0, + transform, + textAlign: 'start' + } + ], + tooltip: false + }) } - ] + } return { ...options,