mirror of
https://github.com/dataease/dataease.git
synced 2026-06-16 19:33:11 +08:00
feat(图表): 支持堆叠条形图
This commit is contained in:
committed by
jianneng-fit2cloud
parent
9bd098d216
commit
6b1dd573bf
@@ -3,11 +3,11 @@ 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 { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
|
||||
import { ViewSpec } from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { Bar } from '@/views/chart/components/js/panel/charts/g2/bar/bar'
|
||||
import { getLineDash } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { getLineDash, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { Chart } from '@antv/g2'
|
||||
|
||||
@@ -52,6 +52,28 @@ export class HorizontalBar extends Bar {
|
||||
}
|
||||
axis: AxisType[] = [...BAR_AXIS_TYPE]
|
||||
|
||||
protected configBasicStyle(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
const { basicStyle } = parseJson(chart.customAttr) || {}
|
||||
const colors =
|
||||
basicStyle?.colors?.map(ele =>
|
||||
basicStyle.gradient
|
||||
? setGradientColor(hexColorToRGBA(ele, basicStyle.alpha), true)
|
||||
: hexColorToRGBA(ele, basicStyle.alpha)
|
||||
) || []
|
||||
const scale = { color: { range: colors }, y: { nice: true } }
|
||||
const style =
|
||||
basicStyle?.radiusColumnBar === 'topRoundAngle'
|
||||
? {
|
||||
radiusTopLeft: basicStyle.columnBarRightAngleRadius,
|
||||
radiusTopRight: basicStyle.columnBarRightAngleRadius
|
||||
}
|
||||
: basicStyle?.radiusColumnBar === 'roundAngle'
|
||||
? { radius: basicStyle.columnBarRightAngleRadius }
|
||||
: { radius: 0 }
|
||||
return { ...options, children: [{ ...children[0], scale, style }, ...children.slice(1)] }
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const tmpOptions = super.configLabel(chart, options)
|
||||
const { children } = tmpOptions
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
import { BAR_EDITOR_PROPERTY } from '@/views/chart/components/js/panel/charts/g2/bar/common'
|
||||
import { flow, parseJson } from '@/views/chart/components/js/util'
|
||||
import {
|
||||
createTooltipWrapper,
|
||||
tooltipCss,
|
||||
ViewSpec
|
||||
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
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 { Chart } from '@antv/g2'
|
||||
import { HorizontalBar } from '@/views/chart/components/js/panel/charts/g2/bar/horizontal-bar'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
/**
|
||||
* 堆叠条形图
|
||||
*/
|
||||
export class HorizontalStackBar extends HorizontalBar {
|
||||
properties = BAR_EDITOR_PROPERTY.filter(ele => ele !== 'threshold')
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
extStack: {
|
||||
name: `${t('chart.stack_item')} / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
}
|
||||
}
|
||||
propertyInner = {
|
||||
...this['propertyInner'],
|
||||
'label-selector': ['color', 'fontSize', 'hPosition', 'labelFormatter'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'tooltipFormatter', 'show']
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { label: labelAttr } = parseJson(chart.customAttr) || {}
|
||||
if (!labelAttr?.show) return options
|
||||
|
||||
const { children } = options
|
||||
const position = {
|
||||
position: labelAttr.position === 'middle' ? 'inside' : labelAttr.position,
|
||||
textAlign: 'start',
|
||||
dy: labelAttr.position === 'top' ? -10 : 0,
|
||||
dx: 0
|
||||
}
|
||||
const transform = [
|
||||
{ type: 'exceedAdjust' },
|
||||
...(labelAttr.fullDisplay ? [] : [{ type: 'overlapHide' }])
|
||||
]
|
||||
|
||||
const labels = [
|
||||
{
|
||||
text: 'value',
|
||||
fillOpacity: 1,
|
||||
fill: labelAttr.color,
|
||||
fontSize: labelAttr.fontSize,
|
||||
...position,
|
||||
formatter: (value, _data) => valueFormatter(value, labelAttr.labelFormatter),
|
||||
transform
|
||||
}
|
||||
]
|
||||
|
||||
return {
|
||||
...options,
|
||||
children: [{ ...children[0], labels }, ...children.slice(1)]
|
||||
}
|
||||
}
|
||||
|
||||
protected configTooltip(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
const { tooltip } = parseJson(chart.customAttr)
|
||||
if (!tooltip.show) {
|
||||
return {
|
||||
...options,
|
||||
children: [{ ...children[0], tooltip: false }, ...children.slice(1)]
|
||||
}
|
||||
}
|
||||
|
||||
const tooltipOptions: ViewSpec = {
|
||||
tooltip: a => a,
|
||||
interaction: {
|
||||
tooltip: {
|
||||
mount: createTooltipWrapper(chart),
|
||||
css: tooltipCss(tooltip),
|
||||
enterable: true,
|
||||
shared: true,
|
||||
bounding: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
position: 'top-right',
|
||||
render: (_, { title, items: originalItems }) => {
|
||||
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
|
||||
const tooltipItems = originalItems
|
||||
const result = []
|
||||
tooltipItems.forEach(item => {
|
||||
const value = valueFormatter(item.value, tooltip.tooltipFormatter)
|
||||
const name = isEmpty(item.category) ? item.field : item.category
|
||||
result.push({ ...item, name, value })
|
||||
})
|
||||
const itemsHtml = result
|
||||
.map(item => {
|
||||
const marker = item.color
|
||||
const label = item.name
|
||||
const value = item.value
|
||||
return TOOLTIP_ITEM_TPL.replace('{marker}', marker)
|
||||
.replace('{label}', label)
|
||||
.replace('{value}', value)
|
||||
})
|
||||
.join('')
|
||||
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
|
||||
return `${titleHtml}${listHtml}`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
...options,
|
||||
children: [{ ...children[0], ...tooltipOptions }, ...children.slice(1)]
|
||||
}
|
||||
}
|
||||
|
||||
protected setupOptions(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
return flow(
|
||||
this.configTheme,
|
||||
this.configBasicStyle,
|
||||
this.configLabel,
|
||||
this.configTooltip,
|
||||
this.configLegend,
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configAnalyse,
|
||||
this.configBarConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
constructor(name = 'bar-stack-horizontal') {
|
||||
super(name)
|
||||
Object.assign(this.intervalOptions, {
|
||||
transform: [{ type: 'stackY' }],
|
||||
coordinate: { transform: [{ type: 'transpose' }] }
|
||||
})
|
||||
this.axis = [...this.axis, 'extStack']
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user