mirror of
https://github.com/dataease/dataease.git
synced 2026-06-16 11:21:44 +08:00
feat(图表): 支持基础状状图
This commit is contained in:
committed by
jianneng-fit2cloud
parent
5ef290d749
commit
fde4d20dfa
@@ -0,0 +1,623 @@
|
||||
import { Chart as G2Column, G2Spec } from '@antv/g2'
|
||||
import { G2ChartView, G2DrawOptions } from '@/views/chart/components/js/panel/types/impl/g2'
|
||||
import {
|
||||
BAR_AXIS_TYPE,
|
||||
BAR_EDITOR_PROPERTY,
|
||||
BAR_EDITOR_PROPERTY_INNER
|
||||
} from '@/views/chart/components/js/panel/charts/g2/bar/common'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { flow, hexColorToRGBA, hexToRgba, parseJson } from '@/views/chart/components/js/util'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { getLineDash, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import {
|
||||
DEFAULT_YAXIS_EXT_STYLE,
|
||||
DEFAULT_YAXIS_STYLE
|
||||
} from '@/views/chart/components/editor/util/chart'
|
||||
import _ from 'lodash'
|
||||
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA: any[] = []
|
||||
export type ViewSpec = { children?: G2Spec[] } & G2Spec
|
||||
|
||||
/**
|
||||
* 柱状图
|
||||
*/
|
||||
export class Bar extends G2ChartView<ViewSpec, G2Column> {
|
||||
properties = BAR_EDITOR_PROPERTY
|
||||
propertyInner = {
|
||||
...BAR_EDITOR_PROPERTY_INNER,
|
||||
'basic-style-selector': [...BAR_EDITOR_PROPERTY_INNER['basic-style-selector'], 'seriesColor'],
|
||||
'label-selector': ['vPosition', 'seriesLabelFormatter', 'showExtremum'],
|
||||
'tooltip-selector': [
|
||||
'fontSize',
|
||||
'color',
|
||||
'backgroundColor',
|
||||
'seriesTooltipFormatter',
|
||||
'show',
|
||||
'carousel'
|
||||
],
|
||||
'y-axis-selector': [...BAR_EDITOR_PROPERTY_INNER['y-axis-selector'], 'axisLabelFormatter']
|
||||
}
|
||||
axis: AxisType[] = [...BAR_AXIS_TYPE]
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_value_axis')} / ${t('chart.quota')}`,
|
||||
type: 'q'
|
||||
}
|
||||
}
|
||||
protected intervalOptions = {
|
||||
type: 'interval',
|
||||
encode: {
|
||||
x: 'field',
|
||||
y: 'value',
|
||||
color: 'category'
|
||||
},
|
||||
axis: {
|
||||
x: {
|
||||
title: false
|
||||
},
|
||||
y: {
|
||||
title: false
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
elementHighlight: {
|
||||
background: true
|
||||
},
|
||||
tooltip: {
|
||||
shared: true
|
||||
}
|
||||
},
|
||||
data: []
|
||||
}
|
||||
|
||||
async drawChart(drawOptions: G2DrawOptions<G2Column>): Promise<G2Column> {
|
||||
const { chart, container, action } = drawOptions
|
||||
chart.container = container
|
||||
if (!chart?.data?.data?.length) {
|
||||
return
|
||||
}
|
||||
const data = cloneDeep(drawOptions.chart.data?.data)
|
||||
const initOptions: ViewSpec = {
|
||||
type: 'view',
|
||||
children: [
|
||||
{
|
||||
...this.intervalOptions,
|
||||
transform: [{ type: 'dodgeX' }],
|
||||
data
|
||||
}
|
||||
]
|
||||
}
|
||||
const options: ViewSpec = this.setupOptions(chart, initOptions)
|
||||
const newChart = new G2Column({ container, autoFit: true })
|
||||
newChart.options(options)
|
||||
newChart.on('interval:click', action)
|
||||
return newChart
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const { label: l } = customAttr
|
||||
// 如果没有启用标签,直接返回
|
||||
if (!l || !l.show) {
|
||||
return options
|
||||
}
|
||||
const { children } = options
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
const formatterMap = labelAttr.seriesLabelFormatter?.reduce((pre, next) => {
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {})
|
||||
const position = {
|
||||
position: l.position === 'middle' ? 'inside' : l.position,
|
||||
textAlign: 'center',
|
||||
dy: l.position === 'top' ? -10 : 0,
|
||||
dx: 0
|
||||
}
|
||||
// contrastReverse 标签颜色在图形背景上对比度低的情况下,从指定色板选择一个对比度最优的颜色
|
||||
// overlapDodgeY 对位置碰撞的标签在 y 方向上进行调整,防止标签重叠
|
||||
// exceedAdjust 自动对标签做溢出检测和矫正,即当标签超出视图区域时,会对标签自动做反方向的位移
|
||||
// overlapHide 对位置碰撞的标签进行隐藏,默认保留前一个,隐藏后一个
|
||||
const transform = {
|
||||
transform: [{ type: 'exceedAdjust' }, { type: 'overlapHide' }]
|
||||
}
|
||||
// 配置标签样式
|
||||
const newLabel = {
|
||||
text: 'value',
|
||||
fillOpacity: 1,
|
||||
fill: data => {
|
||||
const labelCfg = formatterMap?.[data.quotaList[0].id] as SeriesFormatter
|
||||
if (!labelCfg) {
|
||||
return l.color
|
||||
}
|
||||
return labelCfg.color
|
||||
},
|
||||
fontSize: data => {
|
||||
const labelCfg = formatterMap?.[data.quotaList[0].id] as SeriesFormatter
|
||||
if (!labelCfg) {
|
||||
return l.fontSize
|
||||
}
|
||||
return labelCfg.fontSize
|
||||
},
|
||||
...position,
|
||||
formatter: (value, data) => {
|
||||
if (data.EXTREME) {
|
||||
return ''
|
||||
}
|
||||
if (!labelAttr.seriesLabelFormatter?.length) {
|
||||
return data.value
|
||||
}
|
||||
const labelCfg = formatterMap?.[data.quotaList[0].id] as SeriesFormatter
|
||||
if (!labelCfg) {
|
||||
return data.value
|
||||
}
|
||||
if (!labelCfg.show) {
|
||||
return ''
|
||||
}
|
||||
return valueFormatter(value, labelCfg.formatterCfg)
|
||||
},
|
||||
...(l.fullDisplay ? {} : transform)
|
||||
}
|
||||
return {
|
||||
...options,
|
||||
children: [
|
||||
{
|
||||
...children[0],
|
||||
labels: [newLabel]
|
||||
},
|
||||
...children.slice(1)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
protected configTooltip(_chart: Chart, options: ViewSpec): ViewSpec {
|
||||
return options
|
||||
}
|
||||
|
||||
protected configBasicStyle(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const colors: string[] = []
|
||||
if (customAttr.basicStyle) {
|
||||
const basicStyle = customAttr.basicStyle
|
||||
basicStyle.colors.forEach(ele => {
|
||||
let color = hexColorToRGBA(ele, basicStyle.alpha)
|
||||
if (basicStyle.gradient) {
|
||||
color = setGradientColor(color, true, 270)
|
||||
}
|
||||
colors.push(color ? color : hexColorToRGBA(ele, basicStyle.alpha))
|
||||
})
|
||||
}
|
||||
const scale = {
|
||||
color: {
|
||||
range: colors
|
||||
},
|
||||
y: {
|
||||
nice: true
|
||||
}
|
||||
}
|
||||
const basicStyle = parseJson(chart.customAttr).basicStyle
|
||||
const { radiusColumnBar, columnBarRightAngleRadius } = basicStyle
|
||||
let style
|
||||
if (radiusColumnBar === 'topRoundAngle') {
|
||||
style = {
|
||||
radiusTopLeft: columnBarRightAngleRadius,
|
||||
radiusTopRight: columnBarRightAngleRadius
|
||||
}
|
||||
} else if (radiusColumnBar === 'roundAngle') {
|
||||
style = {
|
||||
radius: columnBarRightAngleRadius
|
||||
}
|
||||
} else {
|
||||
style = {
|
||||
radius: 0
|
||||
}
|
||||
}
|
||||
return {
|
||||
...options,
|
||||
children: [
|
||||
{
|
||||
...children[0],
|
||||
scale,
|
||||
style
|
||||
},
|
||||
...children.slice(1)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
protected configLegend(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
return {
|
||||
...options,
|
||||
children: [
|
||||
{
|
||||
...children[0],
|
||||
legend: this.getLegend(chart)
|
||||
},
|
||||
...children.slice(1)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
protected getLegend = (chart: Chart) => {
|
||||
let legend = {}
|
||||
let customStyle: CustomStyle
|
||||
if (chart.customStyle) {
|
||||
customStyle = parseJson(chart.customStyle)
|
||||
// legend
|
||||
if (customStyle.legend) {
|
||||
const l = JSON.parse(JSON.stringify(customStyle.legend))
|
||||
if (l.show) {
|
||||
let position
|
||||
const orient = l.orient
|
||||
const legendSymbol = l.icon
|
||||
const legendSize = l.size
|
||||
const legendFontSize = l.fontSize
|
||||
const legendColor = l.color
|
||||
// position 图例布局
|
||||
// layoutJustifyContent 图例实例布局
|
||||
let layoutJustifyContent = 'center'
|
||||
// 根据图例方向和位置设置布局和位置
|
||||
if (orient === 'horizontal') {
|
||||
// 水平布局
|
||||
position = l.vPosition === 'center' ? 'bottom' : l.vPosition
|
||||
layoutJustifyContent =
|
||||
l.hPosition === 'left' && l.vPosition !== 'center'
|
||||
? 'flex-start'
|
||||
: l.hPosition === 'right' && l.vPosition !== 'center'
|
||||
? 'flex-end'
|
||||
: 'center'
|
||||
} else {
|
||||
// 垂直布局
|
||||
position = l.hPosition === 'center' ? 'left' : l.hPosition
|
||||
layoutJustifyContent =
|
||||
l.vPosition === 'top' && l.hPosition !== 'center'
|
||||
? 'flex-start'
|
||||
: l.vPosition === 'bottom' && l.hPosition !== 'center'
|
||||
? 'flex-end'
|
||||
: 'center'
|
||||
}
|
||||
legend = {
|
||||
color: {
|
||||
orientation: orient,
|
||||
position,
|
||||
layout: {
|
||||
justifyContent: layoutJustifyContent
|
||||
},
|
||||
itemMarker: legendSymbol,
|
||||
itemMarkerSize: legendSize,
|
||||
itemLabelFontSize: legendFontSize,
|
||||
itemLabelFill: legendColor,
|
||||
navPageNumFontSize: legendSize,
|
||||
navPageNumFill: legendColor,
|
||||
navButtonSize: legendSize,
|
||||
navOrientation:
|
||||
position === 'left' || position === 'right' ? 'vertical' : 'horizontal'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
legend = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return legend
|
||||
}
|
||||
|
||||
protected configXAxis(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
const xAxis = this.getAxisConfig(chart, 'xAxis')
|
||||
return {
|
||||
...options,
|
||||
children: [
|
||||
{
|
||||
...children[0],
|
||||
axis: { ...children[0].axis, x: xAxis }
|
||||
},
|
||||
...children.slice(1)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
protected configYAxis(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
const yAxis = this.getAxisConfig(chart, 'yAxis')
|
||||
const tmpOptions = {
|
||||
...options,
|
||||
children: [
|
||||
{
|
||||
...children[0],
|
||||
axis: { ...children[0].axis, y: yAxis }
|
||||
},
|
||||
...children.slice(1)
|
||||
]
|
||||
}
|
||||
const customStyle = parseJson(chart.customStyle)
|
||||
const yAxisAtt = JSON.parse(JSON.stringify(customStyle['yAxis']))
|
||||
if (!yAxisAtt.axisValue?.auto) {
|
||||
return {
|
||||
...tmpOptions,
|
||||
scale: {
|
||||
...options.scale,
|
||||
y: {
|
||||
nice: true,
|
||||
clamp: true,
|
||||
domain: [yAxisAtt.axisValue.min, yAxisAtt.axisValue.max],
|
||||
tickCount: yAxisAtt.axisValue.splitCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmpOptions
|
||||
}
|
||||
|
||||
protected configAnalyse(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { children } = options
|
||||
return {
|
||||
...options,
|
||||
children: [...children, ...this.getAssistLineStyle(chart)]
|
||||
}
|
||||
}
|
||||
protected getAssistLineStyle = (chart: Chart) => {
|
||||
const assistLine = []
|
||||
const senior = parseJson(chart.senior)
|
||||
if (!senior.assistLineCfg?.enable) {
|
||||
return assistLine
|
||||
}
|
||||
const assistLineArr = senior.assistLineCfg.assistLine
|
||||
if (assistLineArr?.length > 0) {
|
||||
const customStyle = parseJson(chart.customStyle)
|
||||
let axisFormatterCfg, axisExtFormatterCfg
|
||||
if (customStyle.yAxis) {
|
||||
const a = JSON.parse(JSON.stringify(customStyle.yAxis))
|
||||
axisFormatterCfg = a.axisLabelFormatter
|
||||
? a.axisLabelFormatter
|
||||
: DEFAULT_YAXIS_STYLE.axisLabelFormatter
|
||||
}
|
||||
if (customStyle.yAxisExt) {
|
||||
const a = JSON.parse(JSON.stringify(customStyle.yAxisExt))
|
||||
axisExtFormatterCfg = a.axisLabelFormatter
|
||||
? a.axisLabelFormatter
|
||||
: DEFAULT_YAXIS_EXT_STYLE.axisLabelFormatter
|
||||
}
|
||||
const fixedLines = assistLineArr.filter(ele => ele.field === '0')
|
||||
const dynamicLineFields = assistLineArr
|
||||
.filter(ele => ele.field === '1')
|
||||
.map(item => item.fieldId)
|
||||
const quotaFields = _.filter(chart.yAxis, ele => ele.summary !== '' && ele.id !== '-1')
|
||||
const quotaExtFields = _.filter(chart.yAxisExt, ele => ele.summary !== '' && ele.id !== '-1')
|
||||
const dynamicLines = chart.data.dynamicAssistLines?.filter(item => {
|
||||
return (
|
||||
dynamicLineFields?.includes(item.fieldId) &&
|
||||
(!!_.find(quotaFields, d => d.id === item.fieldId) ||
|
||||
(!!_.find(quotaExtFields, d => d.id === item.fieldId) &&
|
||||
chart.type.includes('chart-mix')))
|
||||
)
|
||||
})
|
||||
const lines = fixedLines.concat(dynamicLines || [])
|
||||
lines.forEach(item => {
|
||||
const value = parseFloat(item.value)
|
||||
const content =
|
||||
item.name +
|
||||
' : ' +
|
||||
valueFormatter(value, item.yAxisType === 'left' ? axisFormatterCfg : axisExtFormatterCfg)
|
||||
assistLine.push({
|
||||
type: 'lineY',
|
||||
data: [value],
|
||||
style: {
|
||||
stroke: item.color,
|
||||
lineDash: getLineDash(item.lineType)
|
||||
},
|
||||
labels: [
|
||||
{
|
||||
text: content,
|
||||
position: 'left',
|
||||
textBaseline: 'bottom',
|
||||
fill: item.color,
|
||||
background: false,
|
||||
fontSize: item.fontSize ? item.fontSize : 10
|
||||
}
|
||||
]
|
||||
})
|
||||
})
|
||||
}
|
||||
return assistLine
|
||||
}
|
||||
|
||||
protected getAxisConfig(chart: Chart, axisType: string): any {
|
||||
const customStyle = parseJson(chart.customStyle)
|
||||
const axis = JSON.parse(JSON.stringify(customStyle[axisType]))
|
||||
if (customStyle[axisType] && axis.show) {
|
||||
// 轴线
|
||||
const line = {
|
||||
line: axis.axisLine.show,
|
||||
lineStrokeOpacity: 1,
|
||||
lineLineWidth: axis.axisLine.lineStyle.width,
|
||||
lineStroke: axis.axisLine.lineStyle.color,
|
||||
lineLineDash: getLineDash(axis.axisLine.lineStyle.style)
|
||||
}
|
||||
// 刻度
|
||||
const tick = {
|
||||
tick: axis.axisLine.show,
|
||||
tickLineWidth: axis.axisLine.lineStyle.width,
|
||||
tickStroke: axis.axisLine.lineStyle.color,
|
||||
tickStrokeOpacity: 2
|
||||
}
|
||||
// 网格线
|
||||
const grid = {
|
||||
grid: axis.splitLine.show,
|
||||
gridLineWidth: axis.splitLine.lineStyle.width,
|
||||
gridStroke: axis.splitLine.lineStyle.color,
|
||||
gridStrokeOpacity: 1,
|
||||
gridLineDash: getLineDash(axis.splitLine.lineStyle.style)
|
||||
}
|
||||
// 标签(刻度值)
|
||||
const label = {
|
||||
label: axis.axisLabel.show,
|
||||
labelFontSize: axis.axisLabel.fontSize,
|
||||
labelFill: axis.axisLabel.color,
|
||||
labelOpacity: 1,
|
||||
labelFormatter: value => {
|
||||
if (axisType === 'yAxis') {
|
||||
return valueFormatter(value, axis.axisLabelFormatter)
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
// 刻度值旋转角度
|
||||
const rotate = axis.axisLabel.rotate
|
||||
const labelTransform = {
|
||||
type: 'rotate',
|
||||
optionalAngles: !rotate || rotate === 0 ? [] : [rotate],
|
||||
recoverWhenFailed: false
|
||||
}
|
||||
const x = {
|
||||
position: axis.position,
|
||||
// 标题
|
||||
title: axis.nameShow && axis.name ? axis.name : false,
|
||||
titleFontSize: axis.fontSize,
|
||||
titleFill: axis.color,
|
||||
// 轴线
|
||||
...line,
|
||||
// 刻度线
|
||||
...tick,
|
||||
// 网格线
|
||||
...grid,
|
||||
// 刻度值
|
||||
...label,
|
||||
transform: [labelTransform]
|
||||
}
|
||||
return x
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
protected configTheme(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const colors: string[] = []
|
||||
if (customAttr.basicStyle) {
|
||||
const basicStyle = customAttr.basicStyle
|
||||
basicStyle.colors.forEach(ele => {
|
||||
colors.push(hexColorToRGBA(ele, basicStyle.alpha))
|
||||
})
|
||||
}
|
||||
const customStyle = parseJson(chart.customStyle)
|
||||
let bgColor
|
||||
if (customStyle.background) {
|
||||
bgColor = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
|
||||
}
|
||||
const theme = {
|
||||
color: colors[0],
|
||||
category10: colors,
|
||||
category20: colors,
|
||||
view: {
|
||||
viewFill: bgColor
|
||||
}
|
||||
}
|
||||
return { ...options, theme }
|
||||
}
|
||||
|
||||
protected configBarConditions(chart: Chart, options: ViewSpec): ViewSpec {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
if (!threshold.enable) return options
|
||||
const overThreshold = data => {
|
||||
data.forEach(item => {
|
||||
item['conditionColor'] = []
|
||||
const quotaList = item.quotaList.map(q => q.id) ?? []
|
||||
quotaList.forEach(q => {
|
||||
// 定义后,在 handleConditionsStyle 函数中使用
|
||||
let currentValue = item['value']
|
||||
if (chart.type === 'progress-bar') {
|
||||
currentValue = item['originalValue']
|
||||
}
|
||||
const cColor = this.getColorByConditions([].concat(q), currentValue, chart)
|
||||
if (cColor) {
|
||||
item.conditionColor.push(cColor)
|
||||
} else {
|
||||
item.conditionColor = undefined
|
||||
}
|
||||
})
|
||||
})
|
||||
return data
|
||||
}
|
||||
options.children[0].data = {
|
||||
value: options.children[0].data,
|
||||
transform: [
|
||||
{
|
||||
type: 'custom',
|
||||
callback: data => overThreshold(data)
|
||||
}
|
||||
]
|
||||
}
|
||||
options.children[0].style = {
|
||||
...options.children[0].style,
|
||||
fill: d => {
|
||||
if (d.conditionColor) {
|
||||
return d.conditionColor
|
||||
}
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
protected getColorByConditions = (quotaList: any[], values: number | number[], chart) => {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
const currentValue = Array.isArray(values) ? values[1] - values[0] : values
|
||||
if (!currentValue) return undefined
|
||||
// 同样的指标只取最后一个
|
||||
const conditionMap = new Map()
|
||||
for (const condition of threshold.lineThreshold ?? []) {
|
||||
conditionMap.set(condition.fieldId, condition)
|
||||
}
|
||||
for (const condition of conditionMap.values()) {
|
||||
if (chart.type === 'progress-bar' && chart.yAxisExt?.[0]?.id !== quotaList?.[0]) continue
|
||||
if (!quotaList.includes(condition.fieldId) && chart.type !== 'waterfall') continue
|
||||
for (const tc of condition.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)
|
||||
) {
|
||||
let tmpColor = hexToRgba(tc.color, basicStyle.alpha)
|
||||
if (basicStyle.gradient) {
|
||||
const vhAngle = ['bar-horizontal', 'progress-bar'].includes(chart.type) ? 0 : 270
|
||||
tmpColor = setGradientColor(tmpColor, true, vhAngle)
|
||||
}
|
||||
return tmpColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
setupDefaultOptions(chart: ChartObj): ChartObj {
|
||||
chart.senior.functionCfg.emptyDataStrategy = 'ignoreData'
|
||||
return chart
|
||||
}
|
||||
|
||||
constructor(name = 'bar', defaultData = DEFAULT_DATA) {
|
||||
super(name, defaultData)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user