diff --git a/frontend/src/icons/svg/percentage-bar-stack.svg b/frontend/src/icons/svg/percentage-bar-stack.svg
new file mode 100644
index 0000000000..8ca73b2aa2
--- /dev/null
+++ b/frontend/src/icons/svg/percentage-bar-stack.svg
@@ -0,0 +1 @@
+
diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js
index 3705a43288..2ade6d493b 100644
--- a/frontend/src/lang/en.js
+++ b/frontend/src/lang/en.js
@@ -1041,6 +1041,7 @@ export default {
label_shadow: 'Label Shadow',
label_shadow_color: 'Shadow Color',
content_formatter: 'Content Format',
+ label_reserve_decimal_count: 'Reserve Decimal',
inside: 'Inside',
tooltip: 'Tips',
tooltip_item: 'Data Item',
@@ -1117,6 +1118,7 @@ export default {
chart_card: 'KPI Card',
chart_bar: 'Base Bar',
chart_bar_stack: 'Stack Bar',
+ chart_percentage_bar_stack: 'Percentage Stack Bar',
chart_bar_horizontal: 'Horizontal Bar',
chart_bar_stack_horizontal: 'Stack Horizontal Bar',
chart_line: 'Base Line',
diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js
index 60d519697b..59fcb8d111 100644
--- a/frontend/src/lang/tw.js
+++ b/frontend/src/lang/tw.js
@@ -1038,6 +1038,7 @@ export default {
circle: '圓形',
label: '標簽',
label_position: '標簽位置',
+ label_reserve_decimal_count: '保留小数',
label_bg: '標簽背景',
label_shadow: '標簽陰影',
label_shadow_color: '陰影顏色',
@@ -1117,6 +1118,7 @@ export default {
chart_card: '指標卡',
chart_bar: '基礎柱狀圖',
chart_bar_stack: '堆疊柱狀圖',
+ chart_percentage_bar_stack: '百分比柱狀圖',
chart_bar_horizontal: '橫嚮柱狀圖',
chart_bar_stack_horizontal: '橫嚮堆疊柱狀圖',
chart_line: '基礎摺線圖',
diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js
index ce9c2f3be1..6da3fd3e87 100644
--- a/frontend/src/lang/zh.js
+++ b/frontend/src/lang/zh.js
@@ -1040,6 +1040,7 @@ export default {
label_bg: '标签背景',
label_shadow: '标签阴影',
label_shadow_color: '阴影颜色',
+ label_reserve_decimal_count: '保留小数',
content_formatter: '内容格式',
inside: '内',
tooltip: '提示',
@@ -1116,6 +1117,7 @@ export default {
chart_card: '指标卡',
chart_bar: '基础柱状图',
chart_bar_stack: '堆叠柱状图',
+ chart_percentage_bar_stack: '百分比柱状图',
chart_bar_horizontal: '横向柱状图',
chart_bar_stack_horizontal: '横向堆叠柱状图',
chart_line: '基础折线图',
diff --git a/frontend/src/views/chart/chart/bar/bar_antv.js b/frontend/src/views/chart/chart/bar/bar_antv.js
index 65c5e8687b..9c73137ff7 100644
--- a/frontend/src/views/chart/chart/bar/bar_antv.js
+++ b/frontend/src/views/chart/chart/bar/bar_antv.js
@@ -93,6 +93,8 @@ export function baseBarOptionAntV(plot, container, chart, action, isGroup, isSta
} else {
delete options.isStack
}
+ // 目前只有百分比堆叠柱状图需要这个属性,先直接在这边判断而不作为参数传过来
+ options.isPercent = chart.type === 'percentage-bar-stack'
// custom color
options.color = antVCustomColor(chart)
diff --git a/frontend/src/views/chart/chart/chart.js b/frontend/src/views/chart/chart/chart.js
index 5849768991..d7c580b0c6 100644
--- a/frontend/src/views/chart/chart/chart.js
+++ b/frontend/src/views/chart/chart/chart.js
@@ -129,7 +129,8 @@ export const DEFAULT_LABEL = {
suffix: '', // 单位后缀
decimalCount: 2, // 小数位数
thousandSeparator: true// 千分符
- }
+ },
+ reserveDecimalCount: 2 // 百分比堆叠柱状图保留小数位数
}
export const DEFAULT_TOOLTIP = {
show: true,
diff --git a/frontend/src/views/chart/chart/common/common_antv.js b/frontend/src/views/chart/chart/common/common_antv.js
index d67c066803..33bf02c0fe 100644
--- a/frontend/src/views/chart/chart/common/common_antv.js
+++ b/frontend/src/views/chart/chart/common/common_antv.js
@@ -52,7 +52,7 @@ export function getTheme(chart) {
}
}
- return {
+ const theme = {
styleSheet: {
brandColor: colors[0],
paletteQualitative10: colors,
@@ -102,6 +102,12 @@ export function getTheme(chart) {
}
}
}
+ // 百分比堆叠柱状图需要取消 offset,因为在顶部类别占比较低的时候有可能会把标签挤出去
+ // 并且视觉上也比较不舒服
+ if (chart.type === 'percentage-bar-stack') {
+ theme.innerLabels.offset = 0
+ }
+ return theme
}
// 通用label
export function getLabel(chart) {
@@ -148,27 +154,35 @@ export function getLabel(chart) {
extStack = JSON.parse(JSON.stringify(chart.extStack))
}
- if (chart.type === 'bar-stack' || chart.type === 'line-stack' || chart.type === 'bar-stack-horizontal') {
+ if (chart.type === 'bar-stack' ||
+ chart.type === 'line-stack' ||
+ chart.type === 'bar-stack-horizontal' ||
+ chart.type === 'percentage-bar-stack'
+ ) {
+ let f
if (extStack && extStack.length > 0) {
- const f = yAxis[0]
- if (f.formatterCfg) {
- res = valueFormatter(param.value, f.formatterCfg)
- } else {
- res = valueFormatter(param.value, formatterItem)
- }
+ f = yAxis[0]
} else {
for (let i = 0; i < yAxis.length; i++) {
- const f = yAxis[i]
- if (f.name === param.category) {
- if (f.formatterCfg) {
- res = valueFormatter(param.value, f.formatterCfg)
- } else {
- res = valueFormatter(param.value, formatterItem)
- }
+ if (yAxis[i].name === param.category) {
+ f = yAxis[i]
break
}
}
}
+ if (!f) {
+ return res
+ }
+ if (!f.formatterCfg) {
+ f.formatterCfg = formatterItem
+ }
+ // 百分比堆叠柱状图保留小数处理
+ if (chart.type === 'percentage-bar-stack') {
+ f.formatterCfg.type = 'percent'
+ f.formatterCfg.decimalCount = l.reserveDecimalCount
+ f.formatterCfg.thousandSeparator = false
+ }
+ res = valueFormatter(param.value, f.formatterCfg)
} else if (chart.type === 'bar-group') {
const f = yAxis[0]
if (f.formatterCfg) {
@@ -214,7 +228,7 @@ export function getTooltip(chart) {
if (chart.type && chart.type !== 'waterfall') {
tooltip.formatter = function(param) {
let yAxis, extStack
- let res
+ let res = param.value
try {
yAxis = JSON.parse(chart.yaxis)
} catch (e) {
@@ -227,29 +241,37 @@ export function getTooltip(chart) {
}
let obj
- if (chart.type === 'bar-stack' || chart.type === 'line-stack' || chart.type === 'bar-stack-horizontal') {
+ if (chart.type === 'bar-stack' ||
+ chart.type === 'line-stack' ||
+ chart.type === 'bar-stack-horizontal' ||
+ chart.type === 'percentage-bar-stack') {
+ let f
if (extStack && extStack.length > 0) {
obj = { name: param.category, value: param.value }
- const f = yAxis[0]
- if (f.formatterCfg) {
- res = valueFormatter(param.value, f.formatterCfg)
- } else {
- res = valueFormatter(param.value, formatterItem)
- }
+ f = yAxis[0]
} else {
obj = { name: param.category, value: param.value }
for (let i = 0; i < yAxis.length; i++) {
- const f = yAxis[i]
- if (f.name === param.category) {
- if (f.formatterCfg) {
- res = valueFormatter(param.value, f.formatterCfg)
- } else {
- res = valueFormatter(param.value, formatterItem)
- }
+ if (yAxis[i].name === param.category) {
+ f = yAxis[i]
break
}
}
}
+ if (!f) {
+ return res
+ }
+ if (!f.formatterCfg) {
+ f.formatterCfg = formatterItem
+ }
+ if (chart.type === 'percentage-bar-stack') {
+ // 保留小数位数和标签保持一致,这边拿一下标签的配置
+ const l = JSON.parse(JSON.stringify(customAttr.label))
+ f.formatterCfg.type = 'percent'
+ f.formatterCfg.decimalCount = l.reserveDecimalCount
+ f.formatterCfg.thousandSeparator = false
+ }
+ res = valueFormatter(param.value, f.formatterCfg)
} else if (chart.type === 'word-cloud') {
obj = { name: param.text, value: param.value }
for (let i = 0; i < yAxis.length; i++) {
@@ -311,7 +333,13 @@ export function getTooltip(chart) {
}
}
} else {
- tooltip = false
+ // 百分比堆叠柱状图隐藏 tooltip 设置 show 为 false 或者直接设置 tooltip 为 false 都无效,会变成分组显示,
+ // 需要将容器(container)或者内容框(showContent)设置为 false 或者 null 才可以隐藏
+ if (chart.type === 'percentage-bar-stack') {
+ tooltip.showContent = false
+ } else {
+ tooltip = false
+ }
}
}
}
@@ -390,7 +418,8 @@ export function getLegend(chart) {
offsetY: offsetY,
marker: {
symbol: legendSymbol
- }
+ },
+ radio: false // 柱状图图例的聚焦功能,默认先关掉
}
} else {
legend = false
diff --git a/frontend/src/views/chart/chart/util.js b/frontend/src/views/chart/chart/util.js
index 55678128c7..d81b716192 100644
--- a/frontend/src/views/chart/chart/util.js
+++ b/frontend/src/views/chart/chart/util.js
@@ -1168,6 +1168,87 @@ export const TYPE_CONFIGS = [
]
}
},
+ {
+ render: 'antv',
+ category: 'chart.chart_type_compare',
+ value: 'percentage-bar-stack',
+ title: 'chart.chart_percentage_bar_stack',
+ icon: 'percentage-bar-stack',
+ properties: [
+ 'color-selector',
+ 'size-selector-ant-v',
+ 'label-selector-ant-v',
+ 'tooltip-selector-ant-v',
+ 'x-axis-selector-ant-v',
+ 'y-axis-selector-ant-v',
+ 'title-selector-ant-v',
+ 'legend-selector-ant-v'
+ ],
+ propertyInner: {
+ 'color-selector': [
+ 'value',
+ 'colorPanel',
+ 'customColor',
+ 'alpha'
+ ],
+ 'size-selector-ant-v': [
+ 'barDefault',
+ 'barGap'
+ ],
+ 'label-selector-ant-v': [
+ 'show',
+ 'fontSize',
+ 'color',
+ 'position-v',
+ 'reserve-decimal-count'
+ ],
+ 'tooltip-selector-ant-v': [
+ 'show',
+ 'textStyle'
+ ],
+ 'x-axis-selector-ant-v': [
+ 'show',
+ 'position',
+ 'name',
+ 'nameTextStyle',
+ 'splitLine',
+ 'axisForm',
+ 'axisLabel'
+ ],
+ 'y-axis-selector-ant-v': [
+ 'show',
+ 'position',
+ 'name',
+ 'nameTextStyle',
+ 'axisValue',
+ 'splitLine',
+ 'axisForm',
+ 'axisLabel'
+ ],
+ 'title-selector-ant-v': [
+ 'show',
+ 'title',
+ 'fontSize',
+ 'color',
+ 'hPosition',
+ 'isItalic',
+ 'isBolder',
+ 'remarkShow',
+ 'fontFamily',
+ 'letterSpace',
+ 'fontShadow'
+ ],
+ 'legend-selector-ant-v': [
+ 'show',
+ 'icon',
+ 'orient',
+ 'textStyle',
+ 'hPosition',
+ 'vPosition'
+ ]
+ }
+ },
+
{
render: 'antv',
category: 'chart.chart_type_distribute',
diff --git a/frontend/src/views/chart/components/ChartComponentG2.vue b/frontend/src/views/chart/components/ChartComponentG2.vue
index a5ed4d4594..3d2cabcc25 100644
--- a/frontend/src/views/chart/components/ChartComponentG2.vue
+++ b/frontend/src/views/chart/components/ChartComponentG2.vue
@@ -196,6 +196,8 @@ export default {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-stack') {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
+ } else if (chart.type === 'percentage-bar-stack') {
+ this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
} else if (chart.type === 'bar-horizontal') {
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-stack-horizontal') {
diff --git a/frontend/src/views/chart/components/shape-attr/LabelSelectorAntV.vue b/frontend/src/views/chart/components/shape-attr/LabelSelectorAntV.vue
index cb165b637e..d49c97bad9 100644
--- a/frontend/src/views/chart/components/shape-attr/LabelSelectorAntV.vue
+++ b/frontend/src/views/chart/components/shape-attr/LabelSelectorAntV.vue
@@ -29,6 +29,11 @@
+
+
+ {{ option.name }}
+
+
@@ -93,7 +98,7 @@ export default {
}
}
},
- data() {
+ data: function() {
return {
labelForm: JSON.parse(JSON.stringify(DEFAULT_LABEL)),
fontSize: [],
@@ -115,7 +120,12 @@ export default {
],
predefineColors: COLOR_PANEL,
typeList: formatterType,
- unitList: unitList
+ unitList: unitList,
+ reserveDecimalCountOptions: [
+ { name: '取整', value: 0 },
+ { name: '一位', value: 1 },
+ { name: '两位', value: 2 }
+ ]
}
},
watch: {
@@ -179,11 +189,17 @@ export default {
this.labelPosition = this.labelPositionH
} else if (type.includes('pie')) {
this.labelPosition = this.labelPositionPie
+ } else if (type === 'percentage-bar-stack') {
+ // 百分比堆叠柱状图的标签位置为 top 的话最顶上的标签会看不到,这个是 G2plot 的 bug,所以这边暂时先把默认值设置为 middle
+ this.labelForm.position = 'middle'
} else {
this.labelPosition = this.labelPositionV
}
}
},
+ /*
+ 判断该属性是否应该出现在当前视图的标签属性编辑列表中
+ */
showProperty(property) {
return this.propertyInner.includes(property)
}