Skip to content

Commit 7117bff

Browse files
authored
Merge pull request #221 from VisActor/fix/pie-legend
fix: fix pie legend when use default encoding
2 parents 4adaba1 + 6f5b80b commit 7117bff

File tree

5 files changed

+60
-223
lines changed

5 files changed

+60
-223
lines changed

apps/website/docs/zh-CN/playground/vseed.mdx

Lines changed: 27 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -9,227 +9,46 @@ const Demo = () => {
99
const MeasureNames = '__MeaName__'
1010

1111
const vseed: VSeed = {
12-
color: {
13-
colorScheme: ['#7E5DFF', '#ACA2D5', '#5B5F89', '#80E1D9', '#F8BC3B', '#B2596E', '#3E91FF', '#9578BB'],
14-
},
15-
legend: {
16-
enable: true,
17-
labelFontSize: 12,
18-
labelFontColor: '#BBBDC3',
19-
position: 'topRight',
20-
maxSize: 1,
21-
},
22-
label: {
23-
enable: false,
24-
labelColor: '#FDFDFD',
25-
labelFontSize: 12,
26-
},
27-
stackCornerRadius: 6,
28-
barMaxWidth: 72,
29-
xAxis: {
30-
grid: {
31-
visible: false,
32-
gridColor: '#303339',
33-
gridWidth: 1,
34-
},
35-
label: {
36-
visible: true,
37-
labelColor: '#888C93',
38-
labelFontSize: 12,
39-
},
40-
title: {
41-
visible: false,
42-
titleColor: '#BBBDC3',
43-
titleFontSize: 12,
44-
},
45-
line: {
46-
lineColor: '#FDFDFD0F',
47-
},
48-
visible: true,
49-
},
50-
primaryYAxis: {
51-
grid: {
52-
visible: true,
53-
gridColor: '#303339',
54-
gridWidth: 1,
55-
},
56-
label: {
57-
visible: true,
58-
labelColor: '#888C93',
59-
labelFontSize: 12,
60-
},
61-
title: {
62-
visible: true,
63-
titleColor: '#BBBDC3',
64-
titleText: '销售额',
65-
titleFontSize: 12,
66-
},
67-
line: {
68-
lineColor: '#FDFDFD0F',
69-
},
70-
visible: true,
71-
},
72-
secondaryYAxis: {
73-
grid: {
74-
visible: false,
75-
gridColor: '#303339',
76-
gridWidth: 1,
77-
},
78-
label: {
79-
visible: true,
80-
labelColor: '#888C93',
81-
labelFontSize: 12,
82-
},
83-
title: {
84-
visible: true,
85-
titleColor: '#BBBDC3',
86-
titleText: '利润率',
87-
titleFontSize: 12,
88-
},
89-
line: {
90-
lineColor: '#FDFDFD0F',
91-
},
92-
visible: true,
93-
},
94-
lineStyle: [
95-
{
96-
lineStyle: 'solid',
97-
lineWidth: 2,
98-
},
99-
],
100-
pointStyle: [
101-
{
102-
pointSize: 8,
103-
},
104-
],
105-
annotationPoint: [
106-
{
107-
text: '最大销售数量',
108-
textColor: '#FFFFFF',
109-
textFontSize: 12,
110-
textBackgroundColor: '#BCC1CB',
111-
textBackgroundBorderRadius: 3,
112-
textBackgroundBorderWidth: 0,
113-
selector: [
114-
{
115-
field: 'xA_20251113103307_b668',
116-
operator: 'in',
117-
value: ['华东'],
118-
},
119-
{
120-
field: 'pr_20251113103311_60cb',
121-
operator: '>',
122-
value: 9000,
123-
},
124-
],
125-
},
126-
{
127-
text: '最大利润',
128-
textColor: '#FFFFFF',
129-
textFontSize: 12,
130-
textBackgroundColor: '#BCC1CB',
131-
textBackgroundBorderRadius: 3,
132-
textBackgroundBorderWidth: 0,
133-
selector: [
134-
{
135-
field: 'se_20251113103303_9f29',
136-
operator: '>',
137-
value: 60000,
138-
},
139-
],
140-
},
141-
],
142-
barStyle: [],
143-
areaStyle: [],
144-
annotationHorizontalLine: [],
145-
annotationVerticalLine: [],
146-
annotationArea: [],
12+
chartType: 'pie',
14713
measures: [
14814
{
149-
id: 'se_20251113103303_9f29',
150-
alias: 'sum(profit)',
151-
encoding: 'secondaryYAxis',
15+
id: 'sales',
16+
alias: '销售额',
15217
format: {
153-
auto: true,
154-
fractionDigits: 2,
155-
thousandSeparator: true,
15618
type: 'number',
19+
ratio: 1000,
20+
thousandSeparator: true,
21+
decimalPlaces: 0,
22+
symbol: '',
23+
prefix: '利润',
24+
suffix: '$',
15725
},
158-
autoFormat: true,
159-
parentId: '0',
26+
parentId: 0,
16027
},
16128
{
162-
id: 'pr_20251113103311_60cb',
163-
alias: 'sum(amount)',
164-
encoding: 'primaryYAxis',
29+
id: 'profit',
30+
alias: '利润',
31+
autoFormat: true,
16532
format: {
166-
auto: true,
167-
thousandSeparator: true,
16833
type: 'number',
34+
ratio: 1000,
35+
thousandSeparator: true,
36+
decimalPlaces: 0,
37+
symbol: '',
38+
prefix: '利润',
39+
suffix: '$',
16940
},
170-
autoFormat: true,
171-
parentId: '0',
172-
},
173-
],
174-
dimensions: [
175-
{
176-
id: 'xA_20251113103307_b668',
177-
alias: 'area',
178-
encoding: 'xAxis',
179-
autoFormat: true,
180-
},
181-
],
182-
dualChartType: [
183-
{
184-
primary: 'column',
185-
secondary: 'line',
186-
},
187-
{
188-
primary: 'line',
189-
secondary: 'line',
41+
parentId: 1,
19042
},
19143
],
192-
chartType: 'dualAxis',
44+
dimensions: [{ id: 'date', alias: '日期' }],
19345
dataset: [
194-
{
195-
pr_20251113103311_60cb: '11041',
196-
pr_20251125192938_f698: '331.09999999999883',
197-
se_20251113103303_9f29: '607218.6819999996',
198-
xA_20251113103307_b668: '华东',
199-
},
200-
{
201-
pr_20251113103311_60cb: '9700',
202-
pr_20251125192938_f698: '232.15000000000038',
203-
se_20251113103303_9f29: '670885.313',
204-
xA_20251113103307_b668: '中南',
205-
},
206-
{
207-
pr_20251113103311_60cb: '6463',
208-
pr_20251125192938_f698: '234.7500000000018',
209-
se_20251113103303_9f29: '242191.50899999973',
210-
xA_20251113103307_b668: '东北',
211-
},
212-
{
213-
pr_20251113103311_60cb: '5146',
214-
pr_20251125192938_f698: '74.10000000000001',
215-
se_20251113103303_9f29: '431053.2169999998',
216-
xA_20251113103307_b668: '华北',
217-
},
218-
{
219-
pr_20251113103311_60cb: '3399',
220-
pr_20251125192938_f698: '134.20000000000067',
221-
se_20251113103303_9f29: '97636.72800000008',
222-
xA_20251113103307_b668: '西南',
223-
},
224-
{
225-
pr_20251113103311_60cb: '1785',
226-
pr_20251125192938_f698: '53.39999999999989',
227-
se_20251113103303_9f29: '98553.47600000004',
228-
xA_20251113103307_b668: '西北',
229-
},
46+
{ date: '2019', profit: 10000, sales: 200000 },
47+
{ date: '2020', profit: 20000, sales: 400000 },
48+
{ date: '2021', profit: 30000, sales: 600000 },
49+
{ date: '2022', profit: 40000, sales: 800000 },
50+
{ date: '2023', profit: 50000, sales: 1000000 },
23051
],
231-
theme: 'dark',
232-
locale: 'zh-CN',
23352
}
23453

23554
const parseRes = zVSeed.safeParse(vseed)
@@ -271,7 +90,7 @@ const SimpleVSeedRender = (props: { vseed: VSeed }) => {
27190
return
27291
}
27392
const theme = dark ? 'dark' : 'light'
274-
const builder = Builder.from({ ...vseed })
93+
const builder = Builder.from(vseed.theme ? vseed : { ...vseed, theme })
27594
const spec = builder.build()
27695
console.log('builder', builder)
27796
console.log('builder performance', builder.performance)

packages/vseed/src/pipeline/advanced/chart/pipes/encoding/pie.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { unique } from 'remeda'
22
import { MeasureId } from 'src/dataReshape'
3-
import { findAllMeasures } from 'src/pipeline/utils'
4-
import type { AdvancedPipe, Dimension, Dimensions, Encoding, Measure, MeasureGroup, Measures } from 'src/types'
3+
import { findAllMeasures, hasMultipleMeasureInSingleView } from 'src/pipeline/utils'
4+
import type { AdvancedPipe, Dimension, Dimensions, Encoding, Measure, Measures } from 'src/types'
55
import { addColorToEncoding } from './color'
66

77
export const defaultEncodingForPie: AdvancedPipe = (advancedVSeed) => {
88
const { measures: vseedMeasures = [], dimensions = [] } = advancedVSeed
99
const measures = findAllMeasures(vseedMeasures)
1010
const encoding: Encoding = {}
11-
generateDefaultDimensionEncoding(dimensions, encoding)
11+
generateDefaultDimensionEncoding(dimensions, encoding, hasMultipleMeasureInSingleView(vseedMeasures))
1212
generateDefaultMeasureEncoding(measures, encoding)
1313
return { ...advancedVSeed, encoding }
1414
}
@@ -20,16 +20,12 @@ export const encodingForPie: AdvancedPipe = (advancedVSeed) => {
2020
const hasDimensionEncoding = dimensions.some((item: Dimension) => item.encoding)
2121
const hasMeasureEncoding = measures.some((item: Measure) => item.encoding)
2222
const encoding: Encoding = {}
23+
const hasMulti = hasMultipleMeasureInSingleView(vseedMeasures)
2324

2425
if (hasDimensionEncoding) {
25-
const hasMultiMeaureInSingleView =
26-
(measures.length > 1 && vseedMeasures.every((m) => !(m as MeasureGroup).children)) ||
27-
vseedMeasures.some((m) => {
28-
return m && (m as MeasureGroup).children && (m as MeasureGroup).children!.length > 1
29-
})
30-
generateDimensionEncoding(dimensions, encoding, hasMultiMeaureInSingleView)
26+
generateDimensionEncoding(dimensions, encoding, hasMulti)
3127
} else {
32-
generateDefaultDimensionEncoding(dimensions, encoding)
28+
generateDefaultDimensionEncoding(dimensions, encoding, hasMulti)
3329
}
3430

3531
if (hasMeasureEncoding) {
@@ -44,9 +40,15 @@ export const encodingForPie: AdvancedPipe = (advancedVSeed) => {
4440
/**
4541
* --------------------维度--------------------
4642
*/
47-
const generateDefaultDimensionEncoding = (dimensions: Dimensions, encoding: Encoding) => {
43+
const generateDefaultDimensionEncoding = (dimensions: Dimensions, encoding: Encoding, isMultiMeasure: boolean) => {
4844
const uniqueDimIds = unique(dimensions.map((d) => d.id))
49-
encoding.color = uniqueDimIds.slice(0) // 第1个之后的维度用于颜色
45+
46+
if (isMultiMeasure) {
47+
encoding.color = uniqueDimIds.slice(0) // 所有维度都用于color映射,包括MeasureId
48+
} else {
49+
encoding.color = uniqueDimIds.filter((d: string) => d !== MeasureId) // 除了MeasureId之外的所有维度用于color映射
50+
}
51+
5052
encoding.detail = encoding.color
5153
encoding.tooltip = uniqueDimIds.filter((d) => d !== MeasureId) // 展示指标名称之外的所有维度
5254
encoding.label = [] // 默认不展示标签

packages/vseed/src/pipeline/advanced/chart/pipes/measures/buildMeasures.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { AdvancedPipe, MeasureGroup, Measures, MeasureTree, VSeed } from 's
22
import { isMeasureTreeWithChildren, isMeasureTreeWithParentId, normalizeMeasureTree } from './utils'
33
import { isPivotChart } from 'src/pipeline/utils'
44
import { DEFAULT_PARENT_ID } from 'src/pipeline/utils/constant'
5+
import { isValid } from '@visactor/vutils'
56

67
export const buildMeasures: AdvancedPipe = (advancedVSeed) => {
78
// 带Children的指标树, 不进行任何处理
@@ -33,7 +34,7 @@ const generateMeasuresByParentId = (measures: Measures): MeasureTree => {
3334
if (parent && 'children' in parent) {
3435
parent.children = parent.children || []
3536
parent.children.push(measure)
36-
} else if (measure.parentId) {
37+
} else if (isValid(measure.parentId)) {
3738
measureTree.push({
3839
id: measure.parentId,
3940
children: [measure],

packages/vseed/src/pipeline/spec/chart/pipes/pivotChart/pivotIndicators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const pivotIndicators =
5151

5252
const chartSpec = execPipeline(chartPipeline, newContext, {})
5353
return {
54-
indicatorKey: reshapeInfo.id,
54+
indicatorKey: `${reshapeInfo.id}`,
5555
title: measureGroup?.alias,
5656
cellType: 'chart',
5757
chartModule: 'vchart',

packages/vseed/src/pipeline/utils/measures/find.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Measure, MeasureTree } from 'src/types'
1+
import type { Measure, MeasureGroup, MeasureTree } from 'src/types'
22
import { preorderTraverse } from '../tree'
33

44
export const findMeasureById = (measures: MeasureTree = [], id: string): Measure | undefined => {
@@ -41,3 +41,18 @@ export const findAllMeasures = (measures: MeasureTree = []): Measure[] => {
4141
})
4242
return result
4343
}
44+
45+
export const hasMultipleMeasureInSingleView = (measures: MeasureTree = []): boolean => {
46+
if (measures.every((m) => !('children' in m))) {
47+
return measures.length > 1
48+
}
49+
let found = false
50+
preorderTraverse<Measure, 'children'>(measures, (node) => {
51+
if ((node as MeasureGroup).children && (node as MeasureGroup).children!.length > 1) {
52+
found = true
53+
return true
54+
}
55+
return false
56+
})
57+
return found
58+
}

0 commit comments

Comments
 (0)