feat(图表): 柱状图、条形图、折线图、面积图支持按序列设置颜色 #10309

This commit is contained in:
wisonic 2024-07-18 21:11:35 +08:00
parent 366604153f
commit fc55949b84
11 changed files with 539 additions and 38 deletions

View File

@ -124,6 +124,23 @@ declare interface ChartBasicStyle {
* 配色 * 配色
*/ */
colors: string[] colors: string[]
/**
* 多序列颜色
*/
seriesColor: {
/**
* 序列识别id多指标就是轴id分组或者堆叠就是类别值
*/
id: string
/**
* 显示名称
*/
name: string
/**
* 序列颜色
*/
color: string
}[]
/** /**
* 渐变 * 渐变
*/ */

View File

@ -247,9 +247,10 @@ onMounted(() => {
<template v-if="showProperty('colors')"> <template v-if="showProperty('colors')">
<custom-color-style-select <custom-color-style-select
v-model="state" v-model="state"
:chart="chart"
:themes="themes" :themes="themes"
:property-inner="propertyInner" :property-inner="propertyInner"
@change-basic-style="changeBasicStyle('colors')" @change-basic-style="prop => changeBasicStyle(prop)"
/> />
</template> </template>

View File

@ -1,11 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { ElColorPicker, ElPopover } from 'element-plus-secondary' import { ElColorPicker, ElPopover } from 'element-plus-secondary'
import { computed, onMounted, ref } from 'vue' import { computed, nextTick, onMounted, reactive, ref, toRefs, watch } from 'vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { COLOR_CASES, COLOR_PANEL } from '@/views/chart/components/editor/util/chart' import { COLOR_CASES, COLOR_PANEL } from '@/views/chart/components/editor/util/chart'
import GradientColorSelector from '@/views/chart/components/editor/editor-style/components/GradientColorSelector.vue' import GradientColorSelector from '@/views/chart/components/editor/editor-style/components/GradientColorSelector.vue'
import { getMapColorCases, stepsColor } from '@/views/chart/components/js/util' import { getMapColorCases, stepsColor } from '@/views/chart/components/js/util'
import { useEmitt } from '@/hooks/web/useEmitt' import { useEmitt } from '@/hooks/web/useEmitt'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import chartViewManager from '../../../js/panel'
import { G2PlotChartView } from '../../../js/panel/types/impl/g2plot'
import { cloneDeep } from 'lodash-es'
const { t } = useI18n() const { t } = useI18n()
@ -18,12 +23,15 @@ const props = withDefaults(
colorIndex: number colorIndex: number
} }
propertyInner: Array<string> propertyInner: Array<string>
chart: ChartObj
}>(), }>(),
{ {
themes: 'light' themes: 'light'
} }
) )
const dvMainStore = dvMainStoreWithOut()
const { batchOptStatus } = storeToRefs(dvMainStore)
const { chart } = toRefs(props)
const emits = defineEmits(['update:modelValue', 'changeBasicStyle']) const emits = defineEmits(['update:modelValue', 'changeBasicStyle'])
const changeChartType = () => { const changeChartType = () => {
if (isColorGradient.value) { if (isColorGradient.value) {
@ -31,8 +39,89 @@ const changeChartType = () => {
changeColorOption({ value: 'default' }) changeColorOption({ value: 'default' })
} }
} }
const seriesColorPickerRef = ref<InstanceType<typeof ElColorPicker>>()
const seriesColorState = reactive({
curSeriesColor: {
id: '',
name: '',
color: '#000'
} as any,
curColorIndex: 0,
seriesColorPickerId: 'body'
})
const setupSeriesColor = () => {
if (batchOptStatus.value || !chart.value) {
return
}
const instance = chartViewManager.getChartView(
chart.value.render,
chart.value.type
) as G2PlotChartView
if (!instance?.propertyInner?.['basic-style-selector'].includes('seriesColor')) {
return
}
const viewData = dvMainStore.getViewDataDetails(chart.value.id)
if (!viewData) {
return
}
const newSeriesColor = instance.setupSeriesColor(chart.value, viewData.data)
const oldSeriesColor =
state.value.basicStyleForm.seriesColor?.reduce((p, n) => {
p[n.id] = n
return p
}, {}) || {}
newSeriesColor?.forEach(item => {
const oldColorItem = oldSeriesColor[item.id]
if (oldColorItem) {
item.color = oldColorItem.color
}
})
const seriesColor = state.value.basicStyleForm.seriesColor
seriesColor.splice(0, seriesColor.length, ...newSeriesColor)
if (seriesColor.length) {
if (seriesColorState.curColorIndex > seriesColor.length - 1) {
seriesColorState.curColorIndex = 0
}
seriesColorState.curSeriesColor = seriesColor[seriesColorState.curColorIndex]
const targetId = 'series-color-picker-' + seriesColorState.curColorIndex
const target = document.getElementById(targetId)
if (target) {
seriesColorState.seriesColorPickerId = `#${targetId}`
}
}
}
const switchSeriesColor = (seriesColor, index) => {
seriesColorPickerRef.value?.hide()
seriesColorState.curSeriesColor = cloneDeep(seriesColor)
seriesColorState.curColorIndex = index
seriesColorState.seriesColorPickerId = '#series-color-picker-' + index
nextTick(() => {
seriesColorPickerRef.value?.show()
})
}
const changeSeriesColor = () => {
let changed = false
state.value.basicStyleForm.seriesColor.forEach(c => {
if (
c.id === seriesColorState.curSeriesColor.id &&
c.color !== seriesColorState.curSeriesColor.color
) {
changed = true
c.color = seriesColorState.curSeriesColor.color
}
})
changed && changeBasicStyle('seriesColor')
}
watch([chart, chart.value?.type], setupSeriesColor, {
deep: false
})
onMounted(() => { onMounted(() => {
useEmitt({ name: 'chart-type-change', callback: changeChartType }) useEmitt({ name: 'chart-type-change', callback: changeChartType })
useEmitt({ name: 'chart-data-change', callback: setupSeriesColor })
}) })
const state = computed({ const state = computed({
get() { get() {
@ -66,6 +155,10 @@ const changeColorOption = (option?) => {
state.value.basicStyleForm.colors = [...items[0].colors] state.value.basicStyleForm.colors = [...items[0].colors]
state.value.customColor = state.value.basicStyleForm.colors[0] state.value.customColor = state.value.basicStyleForm.colors[0]
state.value.colorIndex = 0 state.value.colorIndex = 0
state.value.basicStyleForm.seriesColor?.forEach((c, i) => {
const length = items[0].colors.length
c.color = items[0].colors[i % length]
})
changeBasicStyle() changeBasicStyle()
} }
} }
@ -101,8 +194,8 @@ const switchColor = (index, c) => {
customColorPickerRef.value?.show() customColorPickerRef.value?.show()
} }
function changeBasicStyle() { function changeBasicStyle(prop = 'colors') {
emits('changeBasicStyle') emits('changeBasicStyle', prop)
} }
const _popoverShow = ref(false) const _popoverShow = ref(false)
@ -245,15 +338,15 @@ const colorItemBorderColor = (index, state) => {
<div <div
v-for="(c, index) in state.basicStyleForm.colors" v-for="(c, index) in state.basicStyleForm.colors"
:key="index" :key="index"
@click="switchColor(index, c)"
class="color-item"
:class="{ :class="{
active: state.colorIndex === index, active: state.colorIndex === index,
hover: isColorGradient ? showColorGradientIndex(index) : true hover: isColorGradient ? showColorGradientIndex(index) : true
}" }"
class="color-item"
:style="{ :style="{
'border-color': colorItemBorderColor(index, state) 'border-color': colorItemBorderColor(index, state)
}" }"
@click="switchColor(index, c)"
> >
<div <div
class="color-item__inner" class="color-item__inner"
@ -286,7 +379,45 @@ const colorItemBorderColor = (index, state) => {
/> />
</div> </div>
</div> </div>
<div
v-if="showProperty('seriesColor') && !batchOptStatus"
class="series-color-setting colors"
>
<div
v-for="(item, index) in state.basicStyleForm.seriesColor"
:key="item.id"
class="color-list-item"
>
<div
:class="{
active: item.id === seriesColorState.curSeriesColor?.id
}"
class="color-item"
@click="switchSeriesColor(item, index)"
>
<div
class="color-item__inner"
:style="{
backgroundColor: item.color
}"
></div>
</div>
<span :title="item.name" class="color-item-name">{{ item.name }}</span>
<div :id="'series-color-picker-' + index"></div>
</div>
</div>
</template> </template>
<teleport :to="seriesColorState.seriesColorPickerId">
<div style="position: absolute; width: 0; height: 0; overflow: hidden">
<el-color-picker
ref="seriesColorPickerRef"
v-model="seriesColorState.curSeriesColor.color"
size="small"
:predefine="predefineColors"
@change="changeSeriesColor"
/>
</div>
</teleport>
</div> </div>
</template> </template>
@ -398,6 +529,63 @@ const colorItemBorderColor = (index, state) => {
} }
} }
} }
.series-color-setting {
max-height: 200px;
overflow-y: auto;
overflow-x: hidden;
width: 100%;
color: @canvas-main-font-color;
font-size: 12px;
font-style: normal;
font-weight: 400;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
&.dark {
color: @canvas-main-font-color-dark;
}
&.colors {
margin-top: 8px;
justify-content: flex-start;
.color-list-item {
display: flex;
flex-direction: row;
justify-content: start;
align-items: flex-start;
.color-item-name {
max-width: 120px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.color-item {
width: 20px;
height: 20px;
border-radius: 3px;
margin-right: 4px;
cursor: pointer;
padding: 2px;
border: solid 1px transparent;
.color-item__inner {
width: 14px;
height: 14px;
border-radius: 1px;
}
&:hover {
border-color: var(--ed-color-primary-99, rgba(51, 112, 255, 0.6));
}
&.active {
border-color: var(--ed-color-primary);
}
}
}
}
.cases-list { .cases-list {
margin: 6px 0; margin: 6px 0;

View File

@ -1485,7 +1485,8 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
gaugeAxisLine: true, gaugeAxisLine: true,
gaugePercentLabel: true, gaugePercentLabel: true,
showSummary: false, showSummary: false,
summaryLabel: '总计' summaryLabel: '总计',
seriesColor: []
} }
export const BASE_VIEW_CONFIG = { export const BASE_VIEW_CONFIG = {

View File

@ -4,7 +4,13 @@ import {
G2PlotChartView, G2PlotChartView,
G2PlotDrawOptions G2PlotDrawOptions
} from '@/views/chart/components/js/panel/types/impl/g2plot' } from '@/views/chart/components/js/panel/types/impl/g2plot'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util' import {
flow,
hexColorToRGBA,
parseJson,
setUpGroupSeriesColor,
setUpStackSeriesColor
} from '@/views/chart/components/js/util'
import { Datum } from '@antv/g2plot' import { Datum } from '@antv/g2plot'
import { valueFormatter } from '@/views/chart/components/js/formatter' import { valueFormatter } from '@/views/chart/components/js/formatter'
import { import {
@ -25,6 +31,7 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
properties = BAR_EDITOR_PROPERTY properties = BAR_EDITOR_PROPERTY
propertyInner = { propertyInner = {
...BAR_EDITOR_PROPERTY_INNER, ...BAR_EDITOR_PROPERTY_INNER,
'basic-style-selector': [...BAR_EDITOR_PROPERTY_INNER['basic-style-selector'], 'seriesColor'],
'label-selector': ['vPosition', 'seriesLabelFormatter'], 'label-selector': ['vPosition', 'seriesLabelFormatter'],
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'], 'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'],
'y-axis-selector': [...BAR_EDITOR_PROPERTY_INNER['y-axis-selector'], 'axisLabelFormatter'] 'y-axis-selector': [...BAR_EDITOR_PROPERTY_INNER['y-axis-selector'], 'axisLabelFormatter']
@ -221,6 +228,8 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
protected setupOptions(chart: Chart, options: ColumnOptions): ColumnOptions { protected setupOptions(chart: Chart, options: ColumnOptions): ColumnOptions {
return flow( return flow(
this.configTheme, this.configTheme,
this.configEmptyDataStrategy,
this.configColor,
this.configBasicStyle, this.configBasicStyle,
this.configLabel, this.configLabel,
this.configTooltip, this.configTooltip,
@ -228,9 +237,8 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
this.configXAxis, this.configXAxis,
this.configYAxis, this.configYAxis,
this.configSlider, this.configSlider,
this.configAnalyse, this.configAnalyse
this.configEmptyDataStrategy )(chart, options, {}, this)
)(chart, options)
} }
setupDefaultOptions(chart: ChartObj): ChartObj { setupDefaultOptions(chart: ChartObj): ChartObj {
@ -293,6 +301,15 @@ export class StackBar extends Bar {
tooltip tooltip
} }
} }
protected configColor(chart: Chart, options: ColumnOptions): ColumnOptions {
return this.configStackColor(chart, options)
}
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setUpStackSeriesColor(chart, data)
}
constructor(name = 'bar-stack') { constructor(name = 'bar-stack') {
super(name) super(name)
this.baseOptions = { this.baseOptions = {
@ -317,6 +334,14 @@ export class GroupBar extends StackBar {
} }
} }
protected configColor(chart: Chart, options: ColumnOptions): ColumnOptions {
return this.configGroupColor(chart, options)
}
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setUpGroupSeriesColor(chart, data)
}
constructor(name = 'bar-group') { constructor(name = 'bar-group') {
super(name) super(name)
this.baseOptions = { this.baseOptions = {
@ -437,15 +462,16 @@ export class PercentageStackBar extends GroupStackBar {
protected setupOptions(chart: Chart, options: ColumnOptions): ColumnOptions { protected setupOptions(chart: Chart, options: ColumnOptions): ColumnOptions {
return flow( return flow(
this.configTheme, this.configTheme,
this.configEmptyDataStrategy,
this.configColor,
this.configBasicStyle, this.configBasicStyle,
this.configLabel, this.configLabel,
this.configTooltip, this.configTooltip,
this.configLegend, this.configLegend,
this.configXAxis, this.configXAxis,
this.configYAxis, this.configYAxis,
this.configSlider, this.configSlider
this.configEmptyDataStrategy )(chart, options, {}, this)
)(chart, options)
} }
constructor() { constructor() {
super('percentage-bar-stack') super('percentage-bar-stack')

View File

@ -5,7 +5,12 @@ import {
import { Bar, BarOptions } from '@antv/g2plot/esm/plots/bar' import { Bar, BarOptions } from '@antv/g2plot/esm/plots/bar'
import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv' import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util' import {
flow,
hexColorToRGBA,
parseJson,
setUpStackSeriesColor
} from '@/views/chart/components/js/util'
import { valueFormatter } from '@/views/chart/components/js/formatter' import { valueFormatter } from '@/views/chart/components/js/formatter'
import { import {
BAR_AXIS_TYPE, BAR_AXIS_TYPE,
@ -33,6 +38,7 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
properties = BAR_EDITOR_PROPERTY properties = BAR_EDITOR_PROPERTY
propertyInner = { propertyInner = {
...BAR_EDITOR_PROPERTY_INNER, ...BAR_EDITOR_PROPERTY_INNER,
'basic-style-selector': [...BAR_EDITOR_PROPERTY_INNER['basic-style-selector'], 'seriesColor'],
'label-selector': ['hPosition', 'seriesLabelFormatter'], 'label-selector': ['hPosition', 'seriesLabelFormatter'],
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'], 'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'],
'x-axis-selector': [...BAR_EDITOR_PROPERTY_INNER['x-axis-selector'], 'axisLabelFormatter'] 'x-axis-selector': [...BAR_EDITOR_PROPERTY_INNER['x-axis-selector'], 'axisLabelFormatter']
@ -257,6 +263,8 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
protected setupOptions(chart: Chart, options: BarOptions): BarOptions { protected setupOptions(chart: Chart, options: BarOptions): BarOptions {
return flow( return flow(
this.configTheme, this.configTheme,
this.configEmptyDataStrategy,
this.configColor,
this.configBasicStyle, this.configBasicStyle,
this.configLabel, this.configLabel,
this.configTooltip, this.configTooltip,
@ -264,9 +272,8 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
this.configXAxis, this.configXAxis,
this.configYAxis, this.configYAxis,
this.configSlider, this.configSlider,
this.configAnalyseHorizontal, this.configAnalyseHorizontal
this.configEmptyDataStrategy )(chart, options, {}, this)
)(chart, options)
} }
constructor(name = 'bar-horizontal') { constructor(name = 'bar-horizontal') {
@ -323,7 +330,12 @@ export class HorizontalStackBar extends HorizontalBar {
tooltip tooltip
} }
} }
protected configColor(chart: Chart, options: BarOptions): BarOptions {
return this.configStackColor(chart, options)
}
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setUpStackSeriesColor(chart, data)
}
constructor(name = 'bar-stack-horizontal') { constructor(name = 'bar-stack-horizontal') {
super(name) super(name)
this.baseOptions = { this.baseOptions = {
@ -393,15 +405,16 @@ export class HorizontalPercentageStackBar extends HorizontalStackBar {
protected setupOptions(chart: Chart, options: BarOptions): BarOptions { protected setupOptions(chart: Chart, options: BarOptions): BarOptions {
return flow( return flow(
this.configTheme, this.configTheme,
this.configEmptyDataStrategy,
this.configColor,
this.configBasicStyle, this.configBasicStyle,
this.configLabel, this.configLabel,
this.configTooltip, this.configTooltip,
this.configLegend, this.configLegend,
this.configXAxis, this.configXAxis,
this.configYAxis, this.configYAxis,
this.configSlider, this.configSlider
this.configEmptyDataStrategy )(chart, options, {}, this)
)(chart, options)
} }
constructor() { constructor() {

View File

@ -5,7 +5,13 @@ import {
import { Area as G2Area, AreaOptions } from '@antv/g2plot/esm/plots/area' import { Area as G2Area, AreaOptions } from '@antv/g2plot/esm/plots/area'
import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv' import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util' import {
flow,
hexColorToRGBA,
parseJson,
setUpGroupSeriesColor,
setUpStackSeriesColor
} from '@/views/chart/components/js/util'
import { valueFormatter } from '@/views/chart/components/js/formatter' import { valueFormatter } from '@/views/chart/components/js/formatter'
import { import {
LINE_AXIS_TYPE, LINE_AXIS_TYPE,
@ -23,7 +29,11 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
properties = LINE_EDITOR_PROPERTY properties = LINE_EDITOR_PROPERTY
propertyInner = { propertyInner = {
...LINE_EDITOR_PROPERTY_INNER, ...LINE_EDITOR_PROPERTY_INNER,
'basic-style-selector': [...LINE_EDITOR_PROPERTY_INNER['basic-style-selector'], 'gradient'], 'basic-style-selector': [
...LINE_EDITOR_PROPERTY_INNER['basic-style-selector'],
'gradient',
'seriesColor'
],
'label-selector': ['seriesLabelFormatter'], 'label-selector': ['seriesLabelFormatter'],
'tooltip-selector': [ 'tooltip-selector': [
...LINE_EDITOR_PROPERTY_INNER['tooltip-selector'], ...LINE_EDITOR_PROPERTY_INNER['tooltip-selector'],
@ -245,6 +255,8 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
protected setupOptions(chart: Chart, options: AreaOptions): AreaOptions { protected setupOptions(chart: Chart, options: AreaOptions): AreaOptions {
return flow( return flow(
this.configTheme, this.configTheme,
this.configEmptyDataStrategy,
this.configColor,
this.configLabel, this.configLabel,
this.configTooltip, this.configTooltip,
this.configBasicStyle, this.configBasicStyle,
@ -252,9 +264,8 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
this.configXAxis, this.configXAxis,
this.configYAxis, this.configYAxis,
this.configSlider, this.configSlider,
this.configAnalyse, this.configAnalyse
this.configEmptyDataStrategy )(chart, options, {}, this)
)(chart, options)
} }
constructor(name = 'area') { constructor(name = 'area') {
@ -300,6 +311,12 @@ export class StackArea extends Area {
return chart return chart
} }
protected configColor(chart: Chart, options: AreaOptions): AreaOptions {
return this.configStackColor(chart, options)
}
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setUpStackSeriesColor(chart, data)
}
protected configTooltip(chart: Chart, options: AreaOptions): AreaOptions { protected configTooltip(chart: Chart, options: AreaOptions): AreaOptions {
const customAttr: DeepPartial<ChartAttr> = parseJson(chart.customAttr) const customAttr: DeepPartial<ChartAttr> = parseJson(chart.customAttr)
const tooltipAttr = customAttr.tooltip const tooltipAttr = customAttr.tooltip

View File

@ -4,7 +4,12 @@ import {
} from '@/views/chart/components/js/panel/types/impl/g2plot' } from '@/views/chart/components/js/panel/types/impl/g2plot'
import { Line as G2Line, LineOptions } from '@antv/g2plot/esm/plots/line' import { Line as G2Line, LineOptions } from '@antv/g2plot/esm/plots/line'
import { getPadding } from '../../common/common_antv' import { getPadding } from '../../common/common_antv'
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util' import {
flow,
hexColorToRGBA,
parseJson,
setUpGroupSeriesColor
} from '@/views/chart/components/js/util'
import { cloneDeep, isEmpty } from 'lodash-es' import { cloneDeep, isEmpty } from 'lodash-es'
import { valueFormatter } from '@/views/chart/components/js/formatter' import { valueFormatter } from '@/views/chart/components/js/formatter'
import { import {
@ -25,6 +30,7 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
properties = LINE_EDITOR_PROPERTY properties = LINE_EDITOR_PROPERTY
propertyInner = { propertyInner = {
...LINE_EDITOR_PROPERTY_INNER, ...LINE_EDITOR_PROPERTY_INNER,
'basic-style-selector': [...LINE_EDITOR_PROPERTY_INNER['basic-style-selector'], 'seriesColor'],
'label-selector': ['seriesLabelFormatter'], 'label-selector': ['seriesLabelFormatter'],
'tooltip-selector': [ 'tooltip-selector': [
...LINE_EDITOR_PROPERTY_INNER['tooltip-selector'], ...LINE_EDITOR_PROPERTY_INNER['tooltip-selector'],
@ -270,10 +276,14 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
tooltip tooltip
} }
} }
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setUpGroupSeriesColor(chart, data)
}
protected setupOptions(chart: Chart, options: LineOptions): LineOptions { protected setupOptions(chart: Chart, options: LineOptions): LineOptions {
return flow( return flow(
this.configTheme, this.configTheme,
this.configEmptyDataStrategy,
this.configGroupColor,
this.configLabel, this.configLabel,
this.configTooltip, this.configTooltip,
this.configBasicStyle, this.configBasicStyle,
@ -282,8 +292,7 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
this.configXAxis, this.configXAxis,
this.configYAxis, this.configYAxis,
this.configSlider, this.configSlider,
this.configAnalyse, this.configAnalyse
this.configEmptyDataStrategy
)(chart, options) )(chart, options)
} }

View File

@ -19,7 +19,13 @@ import {
ChartWrapper ChartWrapper
} from '@/views/chart/components/js/panel/types' } from '@/views/chart/components/js/panel/types'
import { getEngine } from '@antv/g2/esm/core' import { getEngine } from '@antv/g2/esm/core'
import { handleEmptyDataStrategy } from '../../../util' import {
getColor,
getGroupColor,
getStackColor,
handleEmptyDataStrategy,
setupSeriesColor
} from '../../../util'
export interface G2PlotDrawOptions<O> extends AntVDrawOptions<O> { export interface G2PlotDrawOptions<O> extends AntVDrawOptions<O> {
/** /**
@ -69,8 +75,8 @@ export class G2PlotWrapper<O extends PickOptions, P extends Plot<O>> extends Cha
* G2Plot 的图表抽象类 * G2Plot 的图表抽象类
*/ */
export abstract class G2PlotChartView< export abstract class G2PlotChartView<
O extends PickOptions, O extends PickOptions = PickOptions,
P extends Plot<O> P extends Plot<O> = Plot<O>
> extends AntVAbstractChartView { > extends AntVAbstractChartView {
protected static engine = getEngine('canvas') protected static engine = getEngine('canvas')
@ -134,6 +140,25 @@ export abstract class G2PlotChartView<
return handleEmptyDataStrategy(chart, options) return handleEmptyDataStrategy(chart, options)
} }
protected configColor(chart: Chart, options: O): O {
const color = getColor(chart)
return { ...options, color }
}
protected configGroupColor(chart: Chart, options: O): O {
const color = getGroupColor(chart, options)
return { ...options, color }
}
protected configStackColor(chart: Chart, options: O): O {
const color = getStackColor(chart, options)
return { ...options, color }
}
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setupSeriesColor(chart, data)
}
/** /**
* 流式配置公共参数处理常用的配置后续如果有其他通用配置也可以放进来需要单独配置的属性在各个图表自行实现 * 流式配置公共参数处理常用的配置后续如果有其他通用配置也可以放进来需要单独配置的属性在各个图表自行实现
* @param chart 数据库图表对象 * @param chart 数据库图表对象

View File

@ -418,12 +418,16 @@ export function parseJson<T>(str: T | JSONString<T>): T {
return JSON.parse(str) as T return JSON.parse(str) as T
} }
type FlowFunction<P, R> = (param: P, result: R, context?: Record<string, any>) => R type FlowFunction<P, R> = (param: P, result: R, context?: Record<string, any>, thisArg?: any) => R
export function flow<P, R>(...flows: FlowFunction<P, R>[]): FlowFunction<P, R> { export function flow<P, R>(...flows: FlowFunction<P, R>[]): FlowFunction<P, R> {
return (param: P, result: R, context?: Record<string, any>) => { return (param: P, result: R, context?: Record<string, any>, thisArg?: any) => {
return flows.reduce((result: R, flow: FlowFunction<P, R>) => { return flows.reduce((result: R, flow: FlowFunction<P, R>) => {
return flow(param, result, context) if (thisArg) {
return flow.call(thisArg, param, result, context)
} else {
return flow(param, result, context)
}
}, result) }, result)
} }
} }
@ -677,3 +681,202 @@ export const getMapColorCases = colorCases => {
return itemResult return itemResult
}) })
} }
export function getColor(chart: Chart) {
const basicStyle = parseJson(chart.customAttr).basicStyle
const { seriesColor } = basicStyle
if (seriesColor?.length) {
const { yAxis } = chart
const seriesMap = seriesColor.reduce((p, n) => {
p[n.id] = n
return p
}, {})
yAxis?.forEach((axis, index) => {
const curAxisColor = seriesMap[axis.id]
if (curAxisColor) {
if (index + 1 > basicStyle.colors.length) {
basicStyle.colors.push(curAxisColor.color)
} else {
basicStyle.colors[index] = curAxisColor.color
}
}
})
const color = basicStyle.colors.map(c => hexColorToRGBA(c, basicStyle.alpha))
return color
}
}
export function setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
const result: ChartBasicStyle['seriesColor'] = []
const seriesSet = new Set<string>()
const colors = chart.customAttr.basicStyle.colors
const yAxis = chart.yAxis
yAxis?.forEach(axis => {
if (seriesSet.has(axis.id)) {
return
}
seriesSet.add(axis.id)
result.push({
id: axis.id,
name: axis.chartShowName ?? axis.name,
color: colors[(seriesSet.size - 1) % colors.length]
})
})
return result
}
export function getGroupColor<O extends PickOptions = Options>(chart: Chart, options: O) {
const { basicStyle } = parseJson(chart.customAttr)
const { seriesColor } = basicStyle
if (!seriesColor?.length) {
return
}
const seriesMap = seriesColor.reduce((p, n) => {
p[n.id] = n
return p
}, {})
const { yAxis, xAxisExt } = chart
const { data } = options as unknown as Options
if (xAxisExt?.length) {
const seriesSet = new Set()
data?.forEach(d => d.category !== null && seriesSet.add(d.category))
const tmp = [...seriesSet]
tmp.forEach((c, i) => {
const curAxisColor = seriesMap[c as string]
if (curAxisColor) {
if (i + 1 > basicStyle.colors.length) {
basicStyle.colors.push(curAxisColor.color)
} else {
basicStyle.colors[i] = curAxisColor.color
}
}
})
} else {
yAxis?.forEach((axis, index) => {
const curAxisColor = seriesMap[axis.id]
if (curAxisColor) {
if (index + 1 > basicStyle.colors.length) {
basicStyle.colors.push(curAxisColor.color)
} else {
basicStyle.colors[index] = curAxisColor.color
}
}
})
}
const color = basicStyle.colors.map(c => hexColorToRGBA(c, basicStyle.alpha))
return color
}
export function setUpGroupSeriesColor(
chart: ChartObj,
data?: any[]
): ChartBasicStyle['seriesColor'] {
const result: ChartBasicStyle['seriesColor'] = []
const seriesSet = new Set<string>()
const colors = chart.customAttr.basicStyle.colors
const { yAxis, xAxisExt } = chart
if (xAxisExt?.length) {
data?.forEach(d => {
if (d.value === null || d.category === null || seriesSet.has(d.category)) {
return
}
seriesSet.add(d.category)
result.push({
id: d.category,
name: d.category,
color: colors[(seriesSet.size - 1) % colors.length]
})
})
} else {
yAxis?.forEach(axis => {
if (seriesSet.has(axis.id)) {
return
}
seriesSet.add(axis.id)
result.push({
id: axis.id,
name: axis.chartShowName ?? axis.name,
color: colors[(seriesSet.size - 1) % colors.length]
})
})
}
return result
}
export function getStackColor<O extends PickOptions = Options>(chart: Chart, options: O) {
const { basicStyle } = parseJson(chart.customAttr)
const { seriesColor } = basicStyle
if (!seriesColor?.length) {
return
}
const seriesMap = seriesColor.reduce((p, n) => {
p[n.id] = n
return p
}, {})
const { yAxis, extStack } = chart
const { data } = options as unknown as Options
if (extStack?.length) {
const seriesSet = new Set()
data?.forEach(d => d.category !== null && seriesSet.add(d.category))
const tmp = [...seriesSet]
tmp.forEach((c, i) => {
const curAxisColor = seriesMap[c as string]
if (curAxisColor) {
if (i + 1 > basicStyle.colors.length) {
basicStyle.colors.push(curAxisColor.color)
} else {
basicStyle.colors[i] = curAxisColor.color
}
}
})
} else {
yAxis?.forEach((axis, index) => {
const curAxisColor = seriesMap[axis.id]
if (curAxisColor) {
if (index + 1 > basicStyle.colors.length) {
basicStyle.colors.push(curAxisColor.color)
} else {
basicStyle.colors[index] = curAxisColor.color
}
}
})
}
const color = basicStyle.colors.map(c => hexColorToRGBA(c, basicStyle.alpha))
return color
}
export function setUpStackSeriesColor(
chart: ChartObj,
data?: any[]
): ChartBasicStyle['seriesColor'] {
const result: ChartBasicStyle['seriesColor'] = []
const seriesSet = new Set<string>()
const colors = chart.customAttr.basicStyle.colors
const { yAxis, extStack } = chart
if (extStack?.length) {
data?.forEach(d => {
if (d.value === null || d.category === null || seriesSet.has(d.category)) {
return
}
seriesSet.add(d.category)
result.push({
id: d.category,
name: d.category,
color: colors[(seriesSet.size - 1) % colors.length]
})
})
} else {
yAxis?.forEach(axis => {
if (seriesSet.has(axis.id)) {
return
}
seriesSet.add(axis.id)
result.push({
id: axis.id,
name: axis.chartShowName ?? axis.name,
color: colors[(seriesSet.size - 1) % colors.length]
})
})
}
return result
}

View File

@ -177,6 +177,7 @@ const calcData = async (view, callback) => {
} }
} }
dvMainStore.setViewDataDetails(view.id, chartData.value) dvMainStore.setViewDataDetails(view.id, chartData.value)
emitter.emit('chart-data-change')
await renderChart(res, callback) await renderChart(res, callback)
} }
}) })