mirror of
https://github.com/dataease/dataease.git
synced 2026-05-16 14:31:00 +08:00
feat(图表): 柱条图支持条件样式
This commit is contained in:
committed by
jianneng-fit2cloud
parent
4dc0dbff24
commit
0bbfb07ef9
@@ -1936,7 +1936,10 @@ export default {
|
||||
circle_packing_value: 'Circle Size',
|
||||
circle_packing_border_color: 'Border color',
|
||||
circle_packing_border_width: 'Border width',
|
||||
circle_packing_padding: 'Circle padding'
|
||||
circle_packing_padding: 'Circle padding',
|
||||
increase: 'Increase',
|
||||
decrease: 'Decrease',
|
||||
total: 'Total'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: 'Only effective when editing',
|
||||
|
||||
@@ -1975,7 +1975,10 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr
|
||||
circle_packing_value: 'Circle size',
|
||||
circle_packing_border_color: 'Border color',
|
||||
circle_packing_border_width: 'Border width',
|
||||
circle_packing_padding: 'Circle padding'
|
||||
circle_packing_padding: 'Circle padding',
|
||||
increase: 'Increase',
|
||||
decrease: 'Decrease',
|
||||
total: 'Total'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: 'Only effective when editing',
|
||||
|
||||
@@ -1931,7 +1931,10 @@ export default {
|
||||
circle_packing_value: '圓形大小',
|
||||
circle_packing_border_color: '邊線顏色',
|
||||
circle_packing_border_width: '邊線寬度',
|
||||
circle_packing_padding: '圓形間距'
|
||||
circle_packing_padding: '圓形間距',
|
||||
increase: '增加',
|
||||
decrease: '減少',
|
||||
total: '合計'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: '僅編輯時生效',
|
||||
|
||||
@@ -1933,7 +1933,10 @@ export default {
|
||||
circle_packing_value: '圆形大小',
|
||||
circle_packing_border_color: '边线颜色',
|
||||
circle_packing_border_width: '边线宽度',
|
||||
circle_packing_padding: '圆形间距'
|
||||
circle_packing_padding: '圆形间距',
|
||||
increase: '增加',
|
||||
decrease: '减少',
|
||||
total: '合计'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: '仅编辑时生效',
|
||||
|
||||
@@ -34,83 +34,77 @@ const thresholdCondition = {
|
||||
max: '1',
|
||||
type: 'fixed'
|
||||
}
|
||||
const valueOptions = computed(() => {
|
||||
if (props.chart.type === 'symbolic-map') {
|
||||
return [
|
||||
const expressionList = [
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'eq',
|
||||
label: t('chart.filter_eq')
|
||||
},
|
||||
{
|
||||
value: 'not_eq',
|
||||
label: t('chart.filter_not_eq')
|
||||
}
|
||||
]
|
||||
value: 'eq',
|
||||
label: t('chart.filter_eq')
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'lt',
|
||||
label: t('chart.filter_lt')
|
||||
},
|
||||
{
|
||||
value: 'gt',
|
||||
label: t('chart.filter_gt')
|
||||
}
|
||||
]
|
||||
value: 'not_eq',
|
||||
label: t('chart.filter_not_eq')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'lt',
|
||||
label: t('chart.filter_lt')
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'le',
|
||||
label: t('chart.filter_le')
|
||||
},
|
||||
{
|
||||
value: 'ge',
|
||||
label: t('chart.filter_ge')
|
||||
}
|
||||
]
|
||||
value: 'gt',
|
||||
label: t('chart.filter_gt')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'le',
|
||||
label: t('chart.filter_le')
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'between',
|
||||
label: t('chart.filter_between')
|
||||
}
|
||||
]
|
||||
value: 'ge',
|
||||
label: t('chart.filter_ge')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'between',
|
||||
label: t('chart.filter_between')
|
||||
}
|
||||
]
|
||||
}
|
||||
return [
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'lt',
|
||||
label: t('chart.filter_lt')
|
||||
},
|
||||
{
|
||||
value: 'gt',
|
||||
label: t('chart.filter_gt')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'between',
|
||||
label: t('chart.filter_between')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
const filterExpressionListByValue = (list, values) => {
|
||||
return list
|
||||
.map(group => ({
|
||||
...group,
|
||||
options: group.options.filter(option => values.includes(option.value))
|
||||
}))
|
||||
.filter(group => group.options.length > 0)
|
||||
}
|
||||
const valueOptions = computed(() => {
|
||||
if (props.chart.type === 'symbolic-map') {
|
||||
return filterExpressionListByValue(expressionList, [
|
||||
'eq',
|
||||
'not_eq',
|
||||
'lt',
|
||||
'gt',
|
||||
'le',
|
||||
'ge',
|
||||
'between'
|
||||
])
|
||||
}
|
||||
return filterExpressionListByValue(expressionList, ['lt', 'gt', 'le', 'ge', 'between'])
|
||||
})
|
||||
const predefineColors = COLOR_PANEL
|
||||
|
||||
@@ -142,11 +136,30 @@ const isSymbolicMap = computed(() => {
|
||||
return props.chart.type === 'symbolic-map'
|
||||
})
|
||||
|
||||
const isProgressBar = computed(() => {
|
||||
return props.chart.type === 'progress-bar'
|
||||
})
|
||||
|
||||
const isBidirectionalBar = computed(() => {
|
||||
return props.chart.type === 'bidirectional-bar'
|
||||
})
|
||||
|
||||
const isRangeBar = computed(() => {
|
||||
return props.chart.type === 'bar-range'
|
||||
})
|
||||
|
||||
const initFields = () => {
|
||||
let fields = []
|
||||
if (isSymbolicMap.value) {
|
||||
const extBubble = JSON.parse(JSON.stringify(props.chart.extBubble))
|
||||
fields = [...extBubble]
|
||||
} else if (isProgressBar.value) {
|
||||
const yAxisExt = JSON.parse(JSON.stringify(props.chart.yAxisExt))
|
||||
fields = [...yAxisExt]
|
||||
} else if (isBidirectionalBar.value || isRangeBar.value) {
|
||||
const yAxis = JSON.parse(JSON.stringify(props.chart.yAxis))
|
||||
const yAxisExt = JSON.parse(JSON.stringify(props.chart.yAxisExt))
|
||||
fields = [...yAxis, ...yAxisExt]
|
||||
} else {
|
||||
const yAxis = JSON.parse(JSON.stringify(props.chart.yAxis))
|
||||
fields = [...yAxis]
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import {
|
||||
flow,
|
||||
hexColorToRGBA,
|
||||
hexToRgba,
|
||||
parseJson,
|
||||
setUpGroupSeriesColor,
|
||||
setUpStackSeriesColor
|
||||
@@ -243,7 +244,8 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@@ -396,7 +398,8 @@ export class StackBar extends Bar {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@@ -477,7 +480,8 @@ export class GroupBar extends StackBar {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@@ -565,6 +569,54 @@ export class GroupStackBar extends StackBar {
|
||||
}
|
||||
}
|
||||
|
||||
protected customConfigBarConditions(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
if (!threshold.enable) return options
|
||||
const conditions = threshold.lineThreshold ?? []
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
// 辅助函数:获取颜色,根据条件以及值计算
|
||||
const getColorByConditions = (currentValue: number) => {
|
||||
for (let i = 0; i < conditions.length; i++) {
|
||||
for (let j = 0; j < conditions[i].conditions?.length; j++) {
|
||||
const tc = conditions[i].conditions[j]
|
||||
if (
|
||||
(tc.term === 'between' && currentValue >= tc.min && currentValue <= tc.max) ||
|
||||
(tc.term === 'lt' && currentValue < tc.value) ||
|
||||
(tc.term === 'le' && currentValue <= tc.value) ||
|
||||
(tc.term === 'gt' && currentValue > tc.value) ||
|
||||
(tc.term === 'ge' && currentValue >= tc.value)
|
||||
) {
|
||||
let tmpColor = tc.color
|
||||
if (basicStyle.gradient) {
|
||||
const tmp = hexToRgba(tmpColor, basicStyle.alpha)
|
||||
tmpColor = setGradientColor(tmp, true, 270)
|
||||
}
|
||||
return { fill: tmpColor }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const tmpOptions = {
|
||||
...options,
|
||||
columnStyle: data => {
|
||||
return getColorByConditions(data.value)
|
||||
},
|
||||
tooltip: {
|
||||
...options.tooltip,
|
||||
customItems: originalItems => {
|
||||
originalItems.forEach(item => {
|
||||
const color = getColorByConditions(item.data?.value)
|
||||
if (color) {
|
||||
item.color = color.fill
|
||||
}
|
||||
})
|
||||
return originalItems
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmpOptions
|
||||
}
|
||||
|
||||
protected setupOptions(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
return flow(
|
||||
this.configTheme,
|
||||
@@ -577,7 +629,8 @@ export class GroupStackBar extends StackBar {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.customConfigBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@@ -662,7 +715,8 @@ export class PercentageStackBar extends GroupStackBar {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
constructor() {
|
||||
|
||||
@@ -63,7 +63,8 @@ export class BidirectionalHorizontalBar extends G2PlotChartView<
|
||||
'tooltip-selector',
|
||||
'function-cfg',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
'linkage',
|
||||
'threshold'
|
||||
]
|
||||
propertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
@@ -96,7 +97,8 @@ export class BidirectionalHorizontalBar extends G2PlotChartView<
|
||||
'legend-selector': ['icon', 'orient', 'fontSize', 'color', 'hPosition', 'vPosition'],
|
||||
'function-cfg': ['emptyDataStrategy'],
|
||||
'label-selector': ['hPosition', 'vPosition', 'seriesLabelFormatter'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show']
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
|
||||
selectorSpec: EditorSelectorSpec = {
|
||||
@@ -565,7 +567,8 @@ export class BidirectionalHorizontalBar extends G2PlotChartView<
|
||||
this.configYAxis,
|
||||
this.configAnalyse,
|
||||
this.configSlider,
|
||||
this.configEmptyDataStrategy
|
||||
this.configEmptyDataStrategy,
|
||||
this.configBarConditions
|
||||
)(chart, options)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ export const BAR_EDITOR_PROPERTY: EditorProperty[] = [
|
||||
'function-cfg',
|
||||
'assist-line',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
'linkage',
|
||||
'threshold'
|
||||
]
|
||||
export const BAR_RANGE_EDITOR_PROPERTY: EditorProperty[] = [
|
||||
'background-overall-component',
|
||||
@@ -25,7 +26,8 @@ export const BAR_RANGE_EDITOR_PROPERTY: EditorProperty[] = [
|
||||
'legend-selector',
|
||||
'function-cfg',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
'linkage',
|
||||
'threshold'
|
||||
]
|
||||
|
||||
export const BAR_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
@@ -68,7 +70,8 @@ export const BAR_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
'fontShadow'
|
||||
],
|
||||
'legend-selector': ['icon', 'orient', 'fontSize', 'color', 'hPosition', 'vPosition'],
|
||||
'function-cfg': ['slider', 'emptyDataStrategy']
|
||||
'function-cfg': ['slider', 'emptyDataStrategy'],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
|
||||
export const BAR_AXIS_TYPE: AxisType[] = [
|
||||
|
||||
@@ -277,7 +277,8 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyseHorizontal
|
||||
this.configAnalyseHorizontal,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@@ -394,7 +395,8 @@ export class HorizontalStackBar extends HorizontalBar {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyseHorizontal
|
||||
this.configAnalyseHorizontal,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@@ -484,7 +486,8 @@ export class HorizontalPercentageStackBar extends HorizontalStackBar {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyseHorizontal
|
||||
this.configAnalyseHorizontal,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
'title-selector',
|
||||
'function-cfg',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
'linkage',
|
||||
'threshold'
|
||||
]
|
||||
propertyInner = {
|
||||
...BAR_EDITOR_PROPERTY_INNER,
|
||||
@@ -67,7 +68,8 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
'position',
|
||||
'showLengthLimit'
|
||||
],
|
||||
'function-cfg': ['emptyDataStrategy']
|
||||
'function-cfg': ['emptyDataStrategy'],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
axis: AxisType[] = [...BAR_AXIS_TYPE, 'yAxisExt']
|
||||
protected baseOptions: BarOptions = {
|
||||
@@ -106,7 +108,7 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
// 目标与当前都为负 负向小于0为0
|
||||
if (target < 0 && current < 0) {
|
||||
const completionRate = (2 - current / target) * 100
|
||||
return Math.max(completionRate, 0)
|
||||
return Number(Math.max(completionRate, 0).toFixed(2))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -374,7 +376,8 @@ export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
this.configTooltip,
|
||||
this.configLegend,
|
||||
this.configYAxis,
|
||||
this.configEmptyDataStrategy
|
||||
this.configEmptyDataStrategy,
|
||||
this.configBarConditions
|
||||
)(chart, options)
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export class RangeBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
type: 'q'
|
||||
}
|
||||
}
|
||||
properties = BAR_RANGE_EDITOR_PROPERTY
|
||||
properties = BAR_RANGE_EDITOR_PROPERTY.filter(p => p !== 'threshold')
|
||||
propertyInner = {
|
||||
...BAR_EDITOR_PROPERTY_INNER,
|
||||
'label-selector': ['hPosition', 'color', 'fontSize', 'labelFormatter', 'showGap'],
|
||||
|
||||
@@ -29,7 +29,8 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
'title-selector',
|
||||
'legend-selector',
|
||||
'x-axis-selector',
|
||||
'y-axis-selector'
|
||||
'y-axis-selector',
|
||||
'threshold'
|
||||
]
|
||||
propertyInner: EditorPropertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
@@ -71,7 +72,8 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
'axisLabel',
|
||||
'axisLabelFormatter',
|
||||
'showLengthLimit'
|
||||
]
|
||||
],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'filter', 'drill', 'extLabel', 'extTooltip']
|
||||
axisConfig = {
|
||||
@@ -155,7 +157,7 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
return {
|
||||
...options,
|
||||
total: {
|
||||
label: '合计',
|
||||
label: t('chart.total'),
|
||||
style: {
|
||||
fill: setGradientColor(hexColorToRGBA(totalColorRgba, alpha), gradient, 270)
|
||||
}
|
||||
@@ -275,7 +277,7 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
...tmp.legend,
|
||||
items: [
|
||||
{
|
||||
name: '增加',
|
||||
name: t('chart.increase'),
|
||||
value: '',
|
||||
marker: {
|
||||
style: {
|
||||
@@ -284,7 +286,7 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '减少',
|
||||
name: t('chart.decrease'),
|
||||
value: '',
|
||||
marker: {
|
||||
style: {
|
||||
@@ -293,7 +295,7 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '合计',
|
||||
name: t('chart.total'),
|
||||
value: '',
|
||||
marker: {
|
||||
style: {
|
||||
@@ -315,7 +317,8 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
this.configTooltip,
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configMeta
|
||||
this.configMeta,
|
||||
this.configBarConditions
|
||||
)(chart, options)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { hexColorToRGBA, isAlphaColor, isTransparent, measureText, parseJson } from '../../util'
|
||||
import { hexColorToRGBA, hexToRgba, measureText, parseJson } from '../../util'
|
||||
import {
|
||||
DEFAULT_BASIC_STYLE,
|
||||
DEFAULT_LEGEND_STYLE,
|
||||
@@ -34,6 +34,8 @@ import { centroid } from '@turf/centroid'
|
||||
import type { Plot } from '@antv/g2plot'
|
||||
import type { PickOptions } from '@antv/g2plot/lib/core/plot'
|
||||
import { defaults } from 'lodash-es'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t: tI18n } = useI18n()
|
||||
|
||||
export function getPadding(chart: Chart): number[] {
|
||||
if (chart.drill) {
|
||||
@@ -1600,3 +1602,255 @@ export function configYaxisTitleLengthLimit(chart, plot) {
|
||||
ev.view.options.axes.yAxisExt.title.text = wrappedTitle
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理柱条图的条件样式
|
||||
* @param chart
|
||||
* @param options
|
||||
*/
|
||||
export function handelConditionsStyle(chart: Chart, options: O) {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
if (!threshold.enable) return options
|
||||
const conditions = threshold.lineThreshold ?? []
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
// 获取图表类型
|
||||
const chartType = {
|
||||
...getChartTypeFlags(chart)
|
||||
}
|
||||
// 图表字段,用于rawFields
|
||||
const { xField, yField, groupField, seriesField, color } = options
|
||||
// 获取基础颜色
|
||||
const colors =
|
||||
color && Array.isArray(color)
|
||||
? color
|
||||
: basicStyle.gradient
|
||||
? getGradientColors(basicStyle, chartType)
|
||||
: basicStyle.colors
|
||||
const seriesFields = getSeriesFields(chart, options, chartType)
|
||||
// 系列字段个数,瀑布图时默认3个,增加、减少、合计,当其他图表系列字段为空时,默认为1
|
||||
const seriesLength = chartType.isWaterfall ? 3 : seriesFields.length ? seriesFields.length : 1
|
||||
const seriesFieldLengthRef = { current: 0 }
|
||||
const seriesFieldColorMap = getSeriesFieldColorMap(colors, chartType)
|
||||
let rawFields = [xField, groupField, seriesField]
|
||||
// 对称柱条图时,需要添加两个y轴字段
|
||||
rawFields = chartType.isBidirectionalBar
|
||||
? rawFields.concat(yField[0], yField[1])
|
||||
: rawFields.concat(yField)
|
||||
const tmpOption = {
|
||||
...options,
|
||||
rawFields,
|
||||
color: ref =>
|
||||
getColor(
|
||||
ref,
|
||||
seriesFieldColorMap,
|
||||
colors,
|
||||
seriesFieldLengthRef,
|
||||
seriesLength,
|
||||
basicStyle,
|
||||
conditions,
|
||||
xField,
|
||||
yField,
|
||||
seriesField,
|
||||
chart,
|
||||
chartType
|
||||
)
|
||||
}
|
||||
return tmpOption
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图表类型
|
||||
* @param chart
|
||||
*/
|
||||
function getChartTypeFlags(chart: Chart) {
|
||||
// 在没有配置堆叠字段时,判定不是堆叠图
|
||||
const isStack = chart.type.includes('-stack') && chart.extStack?.length
|
||||
// 分组柱状图
|
||||
const isGroupBar = chart.type === 'bar-group'
|
||||
const isWaterfall = chart.type === 'waterfall'
|
||||
// 条形图
|
||||
const isHorizontal = chart.type.includes('-horizontal')
|
||||
const isProgressBar = chart.type === 'progress-bar'
|
||||
const isBidirectionalBar = chart.type === 'bidirectional-bar'
|
||||
return {
|
||||
isStack,
|
||||
isGroupBar,
|
||||
isWaterfall,
|
||||
isHorizontal,
|
||||
isProgressBar,
|
||||
isBidirectionalBar
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取渐变色
|
||||
* @param basicStyle
|
||||
* @param chartType
|
||||
*/
|
||||
function getGradientColors(basicStyle, chartType) {
|
||||
let vhAngle = chartType.isProgressBar ? 0 : 270
|
||||
return basicStyle.colors.map((ele, index) => {
|
||||
const tmp = hexColorToRGBA(ele, basicStyle.alpha)
|
||||
if (chartType.isBidirectionalBar) {
|
||||
vhAngle = 180 - index * 180
|
||||
if (basicStyle.layout === 'vertical') {
|
||||
vhAngle = index === 0 ? 280 : 90
|
||||
}
|
||||
}
|
||||
return setGradientColor(tmp, true, vhAngle)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系列字段
|
||||
* @param chart
|
||||
* @param options
|
||||
* @param chartType
|
||||
*/
|
||||
function getSeriesFields(chart, options, chartType) {
|
||||
let seriesFields =
|
||||
chartType.isStack || chartType.isGroupBar
|
||||
? options.data?.reduce((acc, item) => {
|
||||
const value = item[options.seriesField]
|
||||
if (!acc.includes(value)) acc.push(value)
|
||||
return acc
|
||||
}, [])
|
||||
: chart.yAxis.map(i => i.id)
|
||||
if (chartType.isBidirectionalBar) {
|
||||
seriesFields = [...seriesFields, ...chart.yAxisExt.map(i => i.id)]
|
||||
}
|
||||
return seriesFields.filter(item => item)
|
||||
}
|
||||
|
||||
/**
|
||||
* 特殊图表颜色处理
|
||||
* 瀑布图固定系列字段:增加、减少、合计
|
||||
* @param colors
|
||||
* @param chartType
|
||||
*/
|
||||
function getSeriesFieldColorMap(colors, chartType) {
|
||||
const seriesFieldColorMap = new Map()
|
||||
if (chartType.isWaterfall) {
|
||||
seriesFieldColorMap.set(tI18n('chart.increase'), colors[0])
|
||||
seriesFieldColorMap.set(tI18n('chart.decrease'), colors[1])
|
||||
seriesFieldColorMap.set(tI18n('chart.total'), colors[2])
|
||||
}
|
||||
return seriesFieldColorMap
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取颜色
|
||||
* @param ref 图库返回当前的数据项
|
||||
* @param seriesFieldColorMap 存储系列字段颜色的 Map
|
||||
* @param colors 颜色数组
|
||||
* @param seriesFieldLengthRef 系列字段个数引用,图库color函数会多次调用,优先返回的是系列字段的包括颜色,之后才是系列字段数据项颜色
|
||||
* @param seriesLength 系列字段个数,用于排除掉序列字段的颜色 图表类型为堆叠或分组时,为系列字段的长度,否则为1
|
||||
* @param basicStyle
|
||||
* @param conditions 条件样式
|
||||
* @param xField x轴字段
|
||||
* @param yField y轴字段
|
||||
* @param seriesField 系列字段
|
||||
* @param chart
|
||||
* @param chartType 图表类型
|
||||
*/
|
||||
function getColor(
|
||||
ref,
|
||||
seriesFieldColorMap,
|
||||
colors,
|
||||
seriesFieldLengthRef,
|
||||
seriesLength,
|
||||
basicStyle,
|
||||
conditions,
|
||||
xField,
|
||||
yField,
|
||||
seriesField,
|
||||
chart,
|
||||
chartType
|
||||
) {
|
||||
let vhAngle = chartType.isHorizontal || chartType.isProgressBar ? 0 : 270
|
||||
// 辅助函数:用于获取系列颜色
|
||||
const getColorFromMap = key => {
|
||||
if (seriesFieldColorMap.has(key)) {
|
||||
return seriesFieldColorMap.get(key)
|
||||
}
|
||||
seriesFieldColorMap.set(key, colors[seriesFieldLengthRef.current % colors.length])
|
||||
seriesFieldLengthRef.current++
|
||||
return seriesFieldColorMap.get(key)
|
||||
}
|
||||
// 进度条时,目标值不显示颜色
|
||||
if (chartType.isProgressBar && ref['type'] === 'target') return 'rgba(0, 0, 0, 0)'
|
||||
if (
|
||||
!chartType.isWaterfall &&
|
||||
!chartType.isProgressBar &&
|
||||
!chartType.isBidirectionalBar &&
|
||||
seriesFieldLengthRef.current < seriesLength
|
||||
) {
|
||||
return getColorFromMap(ref[seriesField])
|
||||
}
|
||||
// 瀑布图时,合计字段颜色固定
|
||||
if (chartType.isWaterfall && ref['$$isTotal$$']) return seriesFieldColorMap.get(ref['field'])
|
||||
// 对称条形图时,系列字段特殊处理
|
||||
if (chartType.isBidirectionalBar && seriesFieldLengthRef.current < seriesLength) {
|
||||
return getColorFromMap(ref['series-field-key'])
|
||||
}
|
||||
// 获取当前系列字段的值
|
||||
// 条形图时,值是x轴字段的值
|
||||
let currentValue = chartType.isHorizontal ? ref[xField] : ref[yField]
|
||||
// 进度条时,值是进度值,不计算目标值
|
||||
if (chartType.isProgressBar) currentValue = ref[xField]?.[1] * 100
|
||||
// 对称条形图时,取值字段通过series-field-key获取
|
||||
if (chartType.isBidirectionalBar) currentValue = ref[ref['series-field-key']]
|
||||
// 当前值是数组时,取差值作为当前值,分组堆叠的值是数组
|
||||
if (Array.isArray(currentValue)) currentValue = currentValue[1] - currentValue[0]
|
||||
if (currentValue) {
|
||||
// 获获字段样式数据
|
||||
const fields = conditions.filter(i => {
|
||||
if (chartType.isStack || chartType.isGroupBar || chartType.isWaterfall) {
|
||||
return i.fieldId === chart.yAxis[0].id
|
||||
} else if (chartType.isProgressBar) {
|
||||
return i.fieldId === chart.yAxisExt[0].id
|
||||
} else if (chartType.isBidirectionalBar) {
|
||||
return (
|
||||
i.fieldId ===
|
||||
(ref['series-field-key'] === 'value' ? chart.yAxis[0].id : chart.yAxisExt[0].id)
|
||||
)
|
||||
} else {
|
||||
return i.fieldId === chart.yAxis[0].id && i.field?.name === ref[seriesField]
|
||||
}
|
||||
})
|
||||
if (fields?.length) {
|
||||
// 样式条件判断
|
||||
for (const tc of fields[fields.length - 1].conditions) {
|
||||
if (
|
||||
(tc.term === 'between' && currentValue >= tc.min && currentValue <= tc.max) ||
|
||||
(tc.term === 'lt' && currentValue < tc.value) ||
|
||||
(tc.term === 'le' && currentValue <= tc.value) ||
|
||||
(tc.term === 'gt' && currentValue > tc.value) ||
|
||||
(tc.term === 'ge' && currentValue >= tc.value)
|
||||
) {
|
||||
if (basicStyle.gradient) {
|
||||
const tmp = hexToRgba(tc.color, basicStyle.alpha)
|
||||
// 对称条形图需要根据系列字段的值来设置渐变角度
|
||||
if (chartType.isBidirectionalBar) {
|
||||
const mastAxisSeries = ref['series-field-key'] === 'value' ? 0 : 1
|
||||
vhAngle = 180 - mastAxisSeries * 180
|
||||
if (basicStyle.layout === 'vertical') {
|
||||
vhAngle = mastAxisSeries === 0 ? 280 : 90
|
||||
}
|
||||
}
|
||||
return setGradientColor(tmp, true, vhAngle)
|
||||
}
|
||||
return tc.color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (chartType.isWaterfall)
|
||||
return ref[yField] > 0
|
||||
? seriesFieldColorMap.get(tI18n('chart.increase'))
|
||||
: seriesFieldColorMap.get(tI18n('chart.decrease'))
|
||||
if (chartType.isProgressBar) return colors[0]
|
||||
if (chartType.isBidirectionalBar) return seriesFieldColorMap.get(ref['series-field-key'])
|
||||
return ref[seriesField] ? seriesFieldColorMap.get(ref[seriesField]) : ''
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ import {
|
||||
getTooltip,
|
||||
getXAxis,
|
||||
getYAxis,
|
||||
getConditions
|
||||
getConditions,
|
||||
handelConditionsStyle
|
||||
} from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import {
|
||||
AntVAbstractChartView,
|
||||
@@ -180,6 +181,10 @@ export abstract class G2PlotChartView<
|
||||
}
|
||||
}
|
||||
|
||||
protected configBarConditions(chart: Chart, options: O) {
|
||||
return handelConditionsStyle(chart, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式配置公共参数,处理常用的配置,后续如果有其他通用配置也可以放进来,需要单独配置的属性在各个图表自行实现。
|
||||
* @param chart 数据库图表对象。
|
||||
|
||||
Reference in New Issue
Block a user