@visactor/vseed 0.4.26 → 0.4.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +2 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.js +128 -12
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.d.ts +2 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.js +14 -7
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointCommon.d.ts +1 -0
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointCommon.js +8 -3
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointCommon.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointOfDualAxis.js +3 -3
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointOfDualAxis.js.map +1 -1
- package/dist/esm/types/chartType/area/zArea.d.ts +2 -0
- package/dist/esm/types/chartType/areaPercent/zAreaPercent.d.ts +2 -0
- package/dist/esm/types/chartType/bar/zBar.d.ts +2 -0
- package/dist/esm/types/chartType/barParallel/zBarParallel.d.ts +2 -0
- package/dist/esm/types/chartType/barPercent/zBarPercent.d.ts +2 -0
- package/dist/esm/types/chartType/boxPlot/zBoxPlot.d.ts +2 -0
- package/dist/esm/types/chartType/column/zColumn.d.ts +2 -0
- package/dist/esm/types/chartType/columnParallel/zColumnParallel.d.ts +2 -0
- package/dist/esm/types/chartType/columnPercent/zColumnPercent.d.ts +2 -0
- package/dist/esm/types/chartType/dualAxis/zDualAxis.d.ts +2 -0
- package/dist/esm/types/chartType/histogram/zHistogram.d.ts +2 -0
- package/dist/esm/types/chartType/line/zLine.d.ts +2 -0
- package/dist/esm/types/chartType/raceBar/zRaceBar.d.ts +2 -0
- package/dist/esm/types/chartType/raceColumn/zRaceColumn.d.ts +2 -0
- package/dist/esm/types/chartType/raceLine/zRaceLine.d.ts +2 -0
- package/dist/esm/types/chartType/raceScatter/zRaceScatter.d.ts +2 -0
- package/dist/esm/types/chartType/scatter/zScatter.d.ts +2 -0
- package/dist/esm/types/properties/annotation/annotation.d.ts +2 -0
- package/dist/esm/types/properties/annotation/annotationPoint.d.ts +4 -0
- package/dist/esm/types/properties/annotation/zAnnotationPoint.d.ts +1 -0
- package/dist/esm/types/properties/annotation/zAnnotationPoint.js +1 -0
- package/dist/esm/types/properties/annotation/zAnnotationPoint.js.map +1 -1
- package/dist/esm/types/properties/config/annotation/zAnnotation.js +1 -0
- package/dist/esm/types/properties/config/annotation/zAnnotation.js.map +1 -1
- package/dist/umd/index.js +152 -35
- package/dist/umd/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,21 +1,124 @@
|
|
|
1
|
+
import { autoFormatter, createFormatter, findAllMeasures } from "../../../../utils/index.js";
|
|
2
|
+
import { isDimensionSelector, isFieldSelector, isMeasureSelector, isPartialDatumSelector } from "../../../../../dataSelector/index.js";
|
|
3
|
+
import { isEmpty } from "remeda";
|
|
1
4
|
import { ANNOTATION_Z_INDEX } from "../../../../utils/constant.js";
|
|
2
|
-
import { buildDifferenceCoordinateDatum, buildDifferenceText, getDifferenceLineStackResolveMode, getRuntimeDifferenceValue,
|
|
5
|
+
import { buildDifferenceCoordinateDatum, buildDifferenceText, getDifferenceLineStackResolveMode, getRuntimeDifferenceValue, resolveDifferenceAnchor, usesDifferenceLineElementStackEnd } from "./annotationDifferenceLineCommon.js";
|
|
3
6
|
const DEFAULT_LINE_COLOR = '#BCC1CB';
|
|
4
7
|
const DEFAULT_TEXT_COLOR = '#ffffff';
|
|
5
8
|
const DEFAULT_TEXT_BACKGROUND_COLOR = '#BCC1CB';
|
|
6
9
|
const DEFAULT_TEXT_FONT_SIZE = 12;
|
|
7
|
-
const DEFAULT_EXPAND_DISTANCE = 24;
|
|
8
10
|
const DEFAULT_LINE_WIDTH = 2;
|
|
9
11
|
const DEFAULT_CORNER_RADIUS = 4;
|
|
10
12
|
const DEFAULT_LABEL_PADDING = 4;
|
|
11
13
|
const DEFAULT_END_SYMBOL_SIZE = 12;
|
|
12
14
|
const DEFAULT_END_SYMBOL_REF_X = -4;
|
|
13
|
-
const
|
|
15
|
+
const DEFAULT_GUTTER_BASE_OFFSET = 20;
|
|
16
|
+
const DEFAULT_GUTTER_RIGHT_PADDING = 44;
|
|
17
|
+
const DEFAULT_GUTTER_TOP_PADDING = 36;
|
|
14
18
|
const DEFAULT_BRACKET_LINE_DASH = [
|
|
15
19
|
2,
|
|
16
20
|
2
|
|
17
21
|
];
|
|
22
|
+
const DEFAULT_PERCENT_DIFFERENCE_FORMAT = {
|
|
23
|
+
type: 'percent',
|
|
24
|
+
fractionDigits: 2
|
|
25
|
+
};
|
|
18
26
|
const getDifferenceLinePath = (index, total)=>1 === total ? 'annotationDifferenceLine' : `annotationDifferenceLine[${index}]`;
|
|
27
|
+
const toArray = (value)=>{
|
|
28
|
+
if (Array.isArray(value)) return value;
|
|
29
|
+
return null == value ? [] : [
|
|
30
|
+
value
|
|
31
|
+
];
|
|
32
|
+
};
|
|
33
|
+
const normalizeRegionPadding = (padding)=>{
|
|
34
|
+
if ('number' == typeof padding) return {
|
|
35
|
+
top: padding,
|
|
36
|
+
right: padding,
|
|
37
|
+
bottom: padding,
|
|
38
|
+
left: padding
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
top: padding?.top ?? 0,
|
|
42
|
+
right: padding?.right ?? 0,
|
|
43
|
+
bottom: padding?.bottom ?? 0,
|
|
44
|
+
left: padding?.left ?? 0
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
const mergeDifferenceLineRegionPadding = (spec, paddingPatch)=>{
|
|
48
|
+
const region = spec.region;
|
|
49
|
+
if (!Array.isArray(region) || 0 === region.length) return spec;
|
|
50
|
+
const mergedPadding = normalizeRegionPadding(region[0].padding);
|
|
51
|
+
if (void 0 !== paddingPatch.top) mergedPadding.top = Math.max(mergedPadding.top, paddingPatch.top);
|
|
52
|
+
if (void 0 !== paddingPatch.right) mergedPadding.right = Math.max(mergedPadding.right, paddingPatch.right);
|
|
53
|
+
if (void 0 !== paddingPatch.bottom) mergedPadding.bottom = Math.max(mergedPadding.bottom, paddingPatch.bottom);
|
|
54
|
+
if (void 0 !== paddingPatch.left) mergedPadding.left = Math.max(mergedPadding.left, paddingPatch.left);
|
|
55
|
+
return {
|
|
56
|
+
...spec,
|
|
57
|
+
region: [
|
|
58
|
+
{
|
|
59
|
+
...region[0],
|
|
60
|
+
padding: mergedPadding
|
|
61
|
+
},
|
|
62
|
+
...region.slice(1)
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
const buildFixedGutterExpandDistance = (isHorizontalChart)=>(_markerData, context)=>{
|
|
67
|
+
const region = context?.region;
|
|
68
|
+
const coordinatePoints = Array.isArray(context?.coordinatePoints) ? context.coordinatePoints : [];
|
|
69
|
+
if (!region || 0 === coordinatePoints.length) return 0;
|
|
70
|
+
const { x: regionStartX, y: regionStartY } = region.getLayoutStartPoint();
|
|
71
|
+
const { width } = region.getLayoutRect();
|
|
72
|
+
if (isHorizontalChart) {
|
|
73
|
+
const targetY = regionStartY - DEFAULT_GUTTER_BASE_OFFSET;
|
|
74
|
+
const minY = Math.min(...coordinatePoints.map((point)=>point.y));
|
|
75
|
+
return Math.max(0, minY - targetY);
|
|
76
|
+
}
|
|
77
|
+
const targetX = regionStartX + width + DEFAULT_GUTTER_BASE_OFFSET;
|
|
78
|
+
const maxX = Math.max(...coordinatePoints.map((point)=>point.x));
|
|
79
|
+
return Math.max(0, targetX - maxX);
|
|
80
|
+
};
|
|
81
|
+
const getAxisFormatter = (spec)=>{
|
|
82
|
+
const valueAxisOrient = 'horizontal' === spec.direction ? 'bottom' : 'left';
|
|
83
|
+
const formatMethod = spec.axes?.find((axis)=>axis.orient === valueAxisOrient)?.label?.formatMethod;
|
|
84
|
+
return 'function' == typeof formatMethod ? (value)=>String(formatMethod(value) ?? value) : void 0;
|
|
85
|
+
};
|
|
86
|
+
const getExplicitMeasureFormat = (measure)=>{
|
|
87
|
+
if (measure?.numFormat && !isEmpty(measure.numFormat)) return measure.numFormat;
|
|
88
|
+
if (measure?.format && !isEmpty(measure.format)) return measure.format;
|
|
89
|
+
};
|
|
90
|
+
const inferMeasureIdFromDatum = (anchor, measureIds)=>{
|
|
91
|
+
const candidateValues = [
|
|
92
|
+
anchor.matchedDatum,
|
|
93
|
+
anchor.coordinateDatum
|
|
94
|
+
];
|
|
95
|
+
for (const datum of candidateValues){
|
|
96
|
+
if (!datum) continue;
|
|
97
|
+
const candidates = measureIds.filter((measureId)=>Number(datum[measureId]) === anchor.value);
|
|
98
|
+
if (1 === candidates.length) return candidates[0];
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const inferMeasureIdFromSelector = (selectorValue, measureIdSet)=>{
|
|
102
|
+
const matchedMeasureIds = new Set();
|
|
103
|
+
for (const currentSelector of toArray(selectorValue)){
|
|
104
|
+
if (isMeasureSelector(currentSelector)) {
|
|
105
|
+
if (measureIdSet.has(currentSelector.field)) matchedMeasureIds.add(currentSelector.field);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (!(isFieldSelector(currentSelector) || isDimensionSelector(currentSelector))) {
|
|
109
|
+
if (isPartialDatumSelector(currentSelector)) Object.keys(currentSelector).forEach((field)=>{
|
|
110
|
+
if (measureIdSet.has(field)) matchedMeasureIds.add(field);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return 1 === matchedMeasureIds.size ? Array.from(matchedMeasureIds)[0] : void 0;
|
|
115
|
+
};
|
|
116
|
+
const resolveDifferenceMeasureId = (anchor, selectorValue, measureIds)=>{
|
|
117
|
+
if ('element' !== anchor.mode) return;
|
|
118
|
+
if (1 === measureIds.length) return measureIds[0];
|
|
119
|
+
const measureIdSet = new Set(measureIds);
|
|
120
|
+
return inferMeasureIdFromSelector(selectorValue, measureIdSet) ?? inferMeasureIdFromDatum(anchor, measureIds);
|
|
121
|
+
};
|
|
19
122
|
const assertDifferenceLineConfig = (value, path)=>{
|
|
20
123
|
if ('object' != typeof value || null === value || Array.isArray(value)) throw new Error(`${path} must be an object`);
|
|
21
124
|
const start = value.start;
|
|
@@ -38,6 +141,11 @@ const annotationDifferenceLine_annotationDifferenceLine = (spec, context)=>{
|
|
|
38
141
|
const stackResolveMode = getDifferenceLineStackResolveMode(vseed, advancedVSeed);
|
|
39
142
|
const useElementStackEnd = usesDifferenceLineElementStackEnd(vseed, advancedVSeed);
|
|
40
143
|
const isBracketChart = 'line' === vseed.chartType || 'area' === vseed.chartType;
|
|
144
|
+
const measures = findAllMeasures(advancedVSeed.measures);
|
|
145
|
+
const measureIds = measures.map((measure)=>measure.id);
|
|
146
|
+
const axisFormatter = getAxisFormatter(chartSpec);
|
|
147
|
+
const percentFormatter = createFormatter(DEFAULT_PERCENT_DIFFERENCE_FORMAT);
|
|
148
|
+
const isHorizontalChart = 'horizontal' === chartSpec.direction;
|
|
41
149
|
const markLine = annotationDifferenceLineList.flatMap((annotationDifferenceLine, index)=>{
|
|
42
150
|
try {
|
|
43
151
|
assertDifferenceLineConfig(annotationDifferenceLine, getDifferenceLinePath(index, annotationDifferenceLineList.length));
|
|
@@ -61,16 +169,18 @@ const annotationDifferenceLine_annotationDifferenceLine = (spec, context)=>{
|
|
|
61
169
|
if (start.mode !== end.mode) return [];
|
|
62
170
|
const usesRuntimeStackEnd = useElementStackEnd || ('column' === vseed.chartType || 'bar' === vseed.chartType) && 'element' === start.mode && 'auto' === stackResolveMode;
|
|
63
171
|
const useBracketStyle = isBracketChart || ('column' === vseed.chartType || 'bar' === vseed.chartType) && 'element' === start.mode && 'auto' === stackResolveMode;
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
start.value,
|
|
67
|
-
end.value
|
|
68
|
-
]);
|
|
172
|
+
const connectDirection = isHorizontalChart ? 'top' : 'right';
|
|
173
|
+
const expandDistance = buildFixedGutterExpandDistance(isHorizontalChart);
|
|
69
174
|
const lineColor = annotationDifferenceLine.lineColor ?? theme?.lineColor ?? DEFAULT_LINE_COLOR;
|
|
70
175
|
const textColor = annotationDifferenceLine.textColor ?? theme?.textColor ?? DEFAULT_TEXT_COLOR;
|
|
71
176
|
const textBackgroundColor = annotationDifferenceLine.textBackgroundColor ?? theme?.textBackgroundColor ?? DEFAULT_TEXT_BACKGROUND_COLOR;
|
|
72
177
|
const textFontSize = annotationDifferenceLine.textFontSize ?? theme?.textFontSize ?? DEFAULT_TEXT_FONT_SIZE;
|
|
73
178
|
const differenceType = annotationDifferenceLine.differenceType ?? 'absolute';
|
|
179
|
+
const startMeasureId = resolveDifferenceMeasureId(start, annotationDifferenceLine.start.selector, measureIds);
|
|
180
|
+
const endMeasureId = resolveDifferenceMeasureId(end, annotationDifferenceLine.end.selector, measureIds);
|
|
181
|
+
const sameMeasure = void 0 !== startMeasureId && startMeasureId === endMeasureId;
|
|
182
|
+
const explicitMeasureFormat = sameMeasure ? getExplicitMeasureFormat(measures.find((measure)=>measure.id === startMeasureId)) : void 0;
|
|
183
|
+
const differenceFormatter = 'percent' === differenceType ? percentFormatter : explicitMeasureFormat ? createFormatter(explicitMeasureFormat) : axisFormatter ?? autoFormatter;
|
|
74
184
|
const label = usesRuntimeStackEnd ? {
|
|
75
185
|
visible: true,
|
|
76
186
|
position: 'middle',
|
|
@@ -85,7 +195,7 @@ const annotationDifferenceLine_annotationDifferenceLine = (spec, context)=>{
|
|
|
85
195
|
anchor: end,
|
|
86
196
|
seriesData,
|
|
87
197
|
useElementStackEnd: usesRuntimeStackEnd
|
|
88
|
-
}), differenceType);
|
|
198
|
+
}), differenceType, differenceFormatter);
|
|
89
199
|
} catch {
|
|
90
200
|
return '';
|
|
91
201
|
}
|
|
@@ -109,7 +219,7 @@ const annotationDifferenceLine_annotationDifferenceLine = (spec, context)=>{
|
|
|
109
219
|
visible: true,
|
|
110
220
|
position: 'middle',
|
|
111
221
|
refY: 0,
|
|
112
|
-
text: buildDifferenceText(start.value, end.value, differenceType),
|
|
222
|
+
text: buildDifferenceText(start.value, end.value, differenceType, differenceFormatter),
|
|
113
223
|
style: {
|
|
114
224
|
fill: textColor,
|
|
115
225
|
fontSize: textFontSize
|
|
@@ -132,7 +242,7 @@ const annotationDifferenceLine_annotationDifferenceLine = (spec, context)=>{
|
|
|
132
242
|
autoRange: true,
|
|
133
243
|
zIndex: ANNOTATION_Z_INDEX,
|
|
134
244
|
connectDirection,
|
|
135
|
-
expandDistance
|
|
245
|
+
expandDistance,
|
|
136
246
|
coordinates: (seriesData, relativeSeries)=>{
|
|
137
247
|
try {
|
|
138
248
|
return [
|
|
@@ -205,13 +315,19 @@ const annotationDifferenceLine_annotationDifferenceLine = (spec, context)=>{
|
|
|
205
315
|
}
|
|
206
316
|
});
|
|
207
317
|
const specMarkLine = chartSpec.markLine || [];
|
|
208
|
-
|
|
318
|
+
const nextSpec = {
|
|
209
319
|
...spec,
|
|
210
320
|
markLine: [
|
|
211
321
|
...specMarkLine,
|
|
212
322
|
...markLine
|
|
213
323
|
]
|
|
214
324
|
};
|
|
325
|
+
if (0 === markLine.length) return nextSpec;
|
|
326
|
+
return mergeDifferenceLineRegionPadding(nextSpec, isHorizontalChart ? {
|
|
327
|
+
top: DEFAULT_GUTTER_TOP_PADDING
|
|
328
|
+
} : {
|
|
329
|
+
right: DEFAULT_GUTTER_RIGHT_PADDING
|
|
330
|
+
});
|
|
215
331
|
};
|
|
216
332
|
export { annotationDifferenceLine_annotationDifferenceLine as annotationDifferenceLine };
|
|
217
333
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.ts"],"sourcesContent":["import type { IAreaChartSpec, IBarChartSpec, ICartesianSeries, ILineChartSpec, IMarkLineSpec } from '@visactor/vchart'\nimport type { AnnotationDifferenceLine, VChartSpecPipe } from 'src/types'\nimport { ANNOTATION_Z_INDEX } from '../../../../utils/constant'\nimport {\n buildDifferenceCoordinateDatum,\n buildDifferenceText,\n getDifferenceLineStackResolveMode,\n getRuntimeDifferenceValue,\n inferDifferenceBracketDirection,\n inferDifferenceConnectDirection,\n usesDifferenceLineElementStackEnd,\n resolveDifferenceAnchor,\n} from './annotationDifferenceLineCommon'\n\nconst DEFAULT_LINE_COLOR = '#BCC1CB'\nconst DEFAULT_TEXT_COLOR = '#ffffff'\nconst DEFAULT_TEXT_BACKGROUND_COLOR = '#BCC1CB'\nconst DEFAULT_TEXT_FONT_SIZE = 12\nconst DEFAULT_EXPAND_DISTANCE = 24\nconst DEFAULT_LINE_WIDTH = 2\nconst DEFAULT_CORNER_RADIUS = 4\nconst DEFAULT_LABEL_PADDING = 4\nconst DEFAULT_END_SYMBOL_SIZE = 12\nconst DEFAULT_END_SYMBOL_REF_X = -4\nconst DEFAULT_BRACKET_EXPAND_DISTANCE = 80\nconst DEFAULT_BRACKET_LINE_DASH: [number, number] = [2, 2]\n\nconst getDifferenceLinePath = (index: number, total: number) =>\n total === 1 ? 'annotationDifferenceLine' : `annotationDifferenceLine[${index}]`\n\nconst assertDifferenceLineConfig: (value: unknown, path: string) => asserts value is AnnotationDifferenceLine = (\n value,\n path,\n) => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error(`${path} must be an object`)\n }\n\n const start = (value as Record<string, unknown>).start\n if (typeof start !== 'object' || start === null || Array.isArray(start)) {\n throw new Error(`${path}.start is required`)\n }\n if ((start as Record<string, unknown>).selector == null) {\n throw new Error(`${path}.start.selector is required`)\n }\n\n const end = (value as Record<string, unknown>).end\n if (typeof end !== 'object' || end === null || Array.isArray(end)) {\n throw new Error(`${path}.end is required`)\n }\n if ((end as Record<string, unknown>).selector == null) {\n throw new Error(`${path}.end.selector is required`)\n }\n}\n\nexport const annotationDifferenceLine: VChartSpecPipe = (spec, context) => {\n const { advancedVSeed, vseed } = context\n const annotationDifferenceLine = advancedVSeed.annotation?.annotationDifferenceLine\n\n if (!annotationDifferenceLine) {\n return spec\n }\n\n const theme = advancedVSeed.config?.[vseed.chartType as 'column']?.annotation?.annotationDifferenceLine\n const annotationDifferenceLineList = Array.isArray(annotationDifferenceLine)\n ? annotationDifferenceLine\n : [annotationDifferenceLine]\n const dataset = advancedVSeed.dataset.flat()\n const chartSpec = spec as IBarChartSpec | ILineChartSpec | IAreaChartSpec\n const stackResolveMode = getDifferenceLineStackResolveMode(vseed, advancedVSeed)\n const useElementStackEnd = usesDifferenceLineElementStackEnd(vseed, advancedVSeed)\n const isBracketChart = vseed.chartType === 'line' || vseed.chartType === 'area'\n\n const markLine = annotationDifferenceLineList.flatMap((annotationDifferenceLine, index) => {\n try {\n assertDifferenceLineConfig(\n annotationDifferenceLine,\n getDifferenceLinePath(index, annotationDifferenceLineList.length),\n )\n\n const start = resolveDifferenceAnchor({\n dataset,\n selectorLabel: 'start',\n selectorValue: annotationDifferenceLine.start.selector,\n spec: chartSpec,\n stackResolveMode,\n allowSelectorFallback: !useElementStackEnd,\n })\n const end = resolveDifferenceAnchor({\n dataset,\n selectorLabel: 'end',\n selectorValue: annotationDifferenceLine.end.selector,\n spec: chartSpec,\n stackResolveMode,\n allowSelectorFallback: !useElementStackEnd,\n })\n\n if (!start || !end) {\n return []\n }\n\n if (start.mode !== end.mode) {\n return []\n }\n\n const usesRuntimeStackEnd =\n useElementStackEnd ||\n ((vseed.chartType === 'column' || vseed.chartType === 'bar') &&\n start.mode === 'element' &&\n stackResolveMode === 'auto')\n const useBracketStyle =\n isBracketChart ||\n ((vseed.chartType === 'column' || vseed.chartType === 'bar') &&\n start.mode === 'element' &&\n stackResolveMode === 'auto')\n const isStackedBarElementBracket =\n vseed.chartType === 'bar' && start.mode === 'element' && stackResolveMode === 'auto'\n const connectDirection = useBracketStyle\n ? isStackedBarElementBracket\n ? 'top'\n : inferDifferenceBracketDirection(start, end)\n : inferDifferenceConnectDirection(vseed, [start.value, end.value])\n\n const lineColor = annotationDifferenceLine.lineColor ?? theme?.lineColor ?? DEFAULT_LINE_COLOR\n const textColor = annotationDifferenceLine.textColor ?? theme?.textColor ?? DEFAULT_TEXT_COLOR\n const textBackgroundColor =\n annotationDifferenceLine.textBackgroundColor ?? theme?.textBackgroundColor ?? DEFAULT_TEXT_BACKGROUND_COLOR\n const textFontSize = annotationDifferenceLine.textFontSize ?? theme?.textFontSize ?? DEFAULT_TEXT_FONT_SIZE\n const differenceType = annotationDifferenceLine.differenceType ?? 'absolute'\n\n const label = usesRuntimeStackEnd\n ? {\n visible: true,\n position: 'middle',\n refY: 0,\n formatMethod: (_markData: any[], seriesData: any[]) => {\n try {\n return buildDifferenceText(\n getRuntimeDifferenceValue({\n anchor: start,\n seriesData,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n getRuntimeDifferenceValue({\n anchor: end,\n seriesData,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n differenceType,\n )\n } catch {\n return ''\n }\n },\n style: {\n fill: textColor,\n fontSize: textFontSize,\n },\n labelBackground: {\n visible: true,\n padding: DEFAULT_LABEL_PADDING,\n style: {\n fill: textBackgroundColor,\n fillOpacity: 1,\n stroke: lineColor,\n lineWidth: 1,\n cornerRadius: DEFAULT_CORNER_RADIUS,\n },\n },\n }\n : {\n visible: true,\n position: 'middle',\n refY: 0,\n text: buildDifferenceText(start.value, end.value, differenceType),\n style: {\n fill: textColor,\n fontSize: textFontSize,\n },\n labelBackground: {\n visible: true,\n padding: DEFAULT_LABEL_PADDING,\n style: {\n fill: textBackgroundColor,\n fillOpacity: 1,\n stroke: lineColor,\n lineWidth: 1,\n cornerRadius: DEFAULT_CORNER_RADIUS,\n },\n },\n }\n\n return [\n {\n type: 'type-step',\n autoRange: true,\n zIndex: ANNOTATION_Z_INDEX,\n connectDirection,\n expandDistance: useBracketStyle ? DEFAULT_BRACKET_EXPAND_DISTANCE : DEFAULT_EXPAND_DISTANCE,\n coordinates: (seriesData: any[], relativeSeries: ICartesianSeries) => {\n try {\n return [\n buildDifferenceCoordinateDatum({\n anchor: start,\n seriesData,\n relativeSeries,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n buildDifferenceCoordinateDatum({\n anchor: end,\n seriesData,\n relativeSeries,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n ]\n } catch {\n return []\n }\n },\n line: useBracketStyle\n ? {\n multiSegment: true,\n mainSegmentIndex: 1,\n style: [\n {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n lineDash: DEFAULT_BRACKET_LINE_DASH,\n },\n {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n },\n {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n lineDash: DEFAULT_BRACKET_LINE_DASH,\n },\n ],\n }\n : {\n style: {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n lineDash: [0],\n cornerRadius: DEFAULT_CORNER_RADIUS,\n },\n },\n label,\n startSymbol: {\n visible: false,\n },\n endSymbol: {\n visible: true,\n size: DEFAULT_END_SYMBOL_SIZE,\n refX: DEFAULT_END_SYMBOL_REF_X,\n style: {\n fill: lineColor,\n },\n },\n } as IMarkLineSpec,\n ]\n } catch {\n return []\n }\n })\n\n const specMarkLine = (chartSpec.markLine as IMarkLineSpec[]) || []\n\n return {\n ...spec,\n markLine: [...specMarkLine, ...markLine],\n }\n}\n"],"names":["DEFAULT_LINE_COLOR","DEFAULT_TEXT_COLOR","DEFAULT_TEXT_BACKGROUND_COLOR","DEFAULT_TEXT_FONT_SIZE","DEFAULT_EXPAND_DISTANCE","DEFAULT_LINE_WIDTH","DEFAULT_CORNER_RADIUS","DEFAULT_LABEL_PADDING","DEFAULT_END_SYMBOL_SIZE","DEFAULT_END_SYMBOL_REF_X","DEFAULT_BRACKET_EXPAND_DISTANCE","DEFAULT_BRACKET_LINE_DASH","getDifferenceLinePath","index","total","assertDifferenceLineConfig","value","path","Array","Error","start","end","annotationDifferenceLine","spec","context","advancedVSeed","vseed","theme","annotationDifferenceLineList","dataset","chartSpec","stackResolveMode","getDifferenceLineStackResolveMode","useElementStackEnd","usesDifferenceLineElementStackEnd","isBracketChart","markLine","resolveDifferenceAnchor","usesRuntimeStackEnd","useBracketStyle","isStackedBarElementBracket","connectDirection","inferDifferenceBracketDirection","inferDifferenceConnectDirection","lineColor","textColor","textBackgroundColor","textFontSize","differenceType","label","_markData","seriesData","buildDifferenceText","getRuntimeDifferenceValue","ANNOTATION_Z_INDEX","relativeSeries","buildDifferenceCoordinateDatum","specMarkLine"],"mappings":";;AAcA,MAAMA,qBAAqB;AAC3B,MAAMC,qBAAqB;AAC3B,MAAMC,gCAAgC;AACtC,MAAMC,yBAAyB;AAC/B,MAAMC,0BAA0B;AAChC,MAAMC,qBAAqB;AAC3B,MAAMC,wBAAwB;AAC9B,MAAMC,wBAAwB;AAC9B,MAAMC,0BAA0B;AAChC,MAAMC,2BAA2B;AACjC,MAAMC,kCAAkC;AACxC,MAAMC,4BAA8C;IAAC;IAAG;CAAE;AAE1D,MAAMC,wBAAwB,CAACC,OAAeC,QAC5CA,AAAU,MAAVA,QAAc,6BAA6B,CAAC,yBAAyB,EAAED,MAAM,CAAC,CAAC;AAEjF,MAAME,6BAA0G,CAC9GC,OACAC;IAEA,IAAI,AAAiB,YAAjB,OAAOD,SAAsBA,AAAU,SAAVA,SAAkBE,MAAM,OAAO,CAACF,QAC/D,MAAM,IAAIG,MAAM,GAAGF,KAAK,kBAAkB,CAAC;IAG7C,MAAMG,QAASJ,MAAkC,KAAK;IACtD,IAAI,AAAiB,YAAjB,OAAOI,SAAsBA,AAAU,SAAVA,SAAkBF,MAAM,OAAO,CAACE,QAC/D,MAAM,IAAID,MAAM,GAAGF,KAAK,kBAAkB,CAAC;IAE7C,IAAKG,AAA8C,QAA9CA,MAAkC,QAAQ,EAC7C,MAAM,IAAID,MAAM,GAAGF,KAAK,2BAA2B,CAAC;IAGtD,MAAMI,MAAOL,MAAkC,GAAG;IAClD,IAAI,AAAe,YAAf,OAAOK,OAAoBA,AAAQ,SAARA,OAAgBH,MAAM,OAAO,CAACG,MAC3D,MAAM,IAAIF,MAAM,GAAGF,KAAK,gBAAgB,CAAC;IAE3C,IAAKI,AAA4C,QAA5CA,IAAgC,QAAQ,EAC3C,MAAM,IAAIF,MAAM,GAAGF,KAAK,yBAAyB,CAAC;AAEtD;AAEO,MAAMK,oDAA2C,CAACC,MAAMC;IAC7D,MAAM,EAAEC,aAAa,EAAEC,KAAK,EAAE,GAAGF;IACjC,MAAMF,2BAA2BG,cAAc,UAAU,EAAE;IAE3D,IAAI,CAACH,0BACH,OAAOC;IAGT,MAAMI,QAAQF,cAAc,MAAM,EAAE,CAACC,MAAM,SAAS,CAAa,EAAE,YAAY;IAC/E,MAAME,+BAA+BV,MAAM,OAAO,CAACI,4BAC/CA,2BACA;QAACA;KAAyB;IAC9B,MAAMO,UAAUJ,cAAc,OAAO,CAAC,IAAI;IAC1C,MAAMK,YAAYP;IAClB,MAAMQ,mBAAmBC,kCAAkCN,OAAOD;IAClE,MAAMQ,qBAAqBC,kCAAkCR,OAAOD;IACpE,MAAMU,iBAAiBT,AAAoB,WAApBA,MAAM,SAAS,IAAeA,AAAoB,WAApBA,MAAM,SAAS;IAEpE,MAAMU,WAAWR,6BAA6B,OAAO,CAAC,CAACN,0BAA0BT;QAC/E,IAAI;YACFE,2BACEO,0BACAV,sBAAsBC,OAAOe,6BAA6B,MAAM;YAGlE,MAAMR,QAAQiB,wBAAwB;gBACpCR;gBACA,eAAe;gBACf,eAAeP,yBAAyB,KAAK,CAAC,QAAQ;gBACtD,MAAMQ;gBACNC;gBACA,uBAAuB,CAACE;YAC1B;YACA,MAAMZ,MAAMgB,wBAAwB;gBAClCR;gBACA,eAAe;gBACf,eAAeP,yBAAyB,GAAG,CAAC,QAAQ;gBACpD,MAAMQ;gBACNC;gBACA,uBAAuB,CAACE;YAC1B;YAEA,IAAI,CAACb,SAAS,CAACC,KACb,OAAO,EAAE;YAGX,IAAID,MAAM,IAAI,KAAKC,IAAI,IAAI,EACzB,OAAO,EAAE;YAGX,MAAMiB,sBACJL,sBACEP,AAAAA,CAAAA,AAAoB,aAApBA,MAAM,SAAS,IAAiBA,AAAoB,UAApBA,MAAM,SAAS,AAAS,KACxDN,AAAe,cAAfA,MAAM,IAAI,IACVW,AAAqB,WAArBA;YACJ,MAAMQ,kBACJJ,kBACET,AAAAA,CAAAA,AAAoB,aAApBA,MAAM,SAAS,IAAiBA,AAAoB,UAApBA,MAAM,SAAS,AAAS,KACxDN,AAAe,cAAfA,MAAM,IAAI,IACVW,AAAqB,WAArBA;YACJ,MAAMS,6BACJd,AAAoB,UAApBA,MAAM,SAAS,IAAcN,AAAe,cAAfA,MAAM,IAAI,IAAkBW,AAAqB,WAArBA;YAC3D,MAAMU,mBAAmBF,kBACrBC,6BACE,QACAE,gCAAgCtB,OAAOC,OACzCsB,gCAAgCjB,OAAO;gBAACN,MAAM,KAAK;gBAAEC,IAAI,KAAK;aAAC;YAEnE,MAAMuB,YAAYtB,yBAAyB,SAAS,IAAIK,OAAO,aAAa3B;YAC5E,MAAM6C,YAAYvB,yBAAyB,SAAS,IAAIK,OAAO,aAAa1B;YAC5E,MAAM6C,sBACJxB,yBAAyB,mBAAmB,IAAIK,OAAO,uBAAuBzB;YAChF,MAAM6C,eAAezB,yBAAyB,YAAY,IAAIK,OAAO,gBAAgBxB;YACrF,MAAM6C,iBAAiB1B,yBAAyB,cAAc,IAAI;YAElE,MAAM2B,QAAQX,sBACV;gBACE,SAAS;gBACT,UAAU;gBACV,MAAM;gBACN,cAAc,CAACY,WAAkBC;oBAC/B,IAAI;wBACF,OAAOC,oBACLC,0BAA0B;4BACxB,QAAQjC;4BACR+B;4BACA,oBAAoBb;wBACtB,IACAe,0BAA0B;4BACxB,QAAQhC;4BACR8B;4BACA,oBAAoBb;wBACtB,IACAU;oBAEJ,EAAE,OAAM;wBACN,OAAO;oBACT;gBACF;gBACA,OAAO;oBACL,MAAMH;oBACN,UAAUE;gBACZ;gBACA,iBAAiB;oBACf,SAAS;oBACT,SAASxC;oBACT,OAAO;wBACL,MAAMuC;wBACN,aAAa;wBACb,QAAQF;wBACR,WAAW;wBACX,cAActC;oBAChB;gBACF;YACF,IACA;gBACE,SAAS;gBACT,UAAU;gBACV,MAAM;gBACN,MAAM8C,oBAAoBhC,MAAM,KAAK,EAAEC,IAAI,KAAK,EAAE2B;gBAClD,OAAO;oBACL,MAAMH;oBACN,UAAUE;gBACZ;gBACA,iBAAiB;oBACf,SAAS;oBACT,SAASxC;oBACT,OAAO;wBACL,MAAMuC;wBACN,aAAa;wBACb,QAAQF;wBACR,WAAW;wBACX,cAActC;oBAChB;gBACF;YACF;YAEJ,OAAO;gBACL;oBACE,MAAM;oBACN,WAAW;oBACX,QAAQgD;oBACRb;oBACA,gBAAgBF,kBAAkB7B,kCAAkCN;oBACpE,aAAa,CAAC+C,YAAmBI;wBAC/B,IAAI;4BACF,OAAO;gCACLC,+BAA+B;oCAC7B,QAAQpC;oCACR+B;oCACAI;oCACA,oBAAoBjB;gCACtB;gCACAkB,+BAA+B;oCAC7B,QAAQnC;oCACR8B;oCACAI;oCACA,oBAAoBjB;gCACtB;6BACD;wBACH,EAAE,OAAM;4BACN,OAAO,EAAE;wBACX;oBACF;oBACA,MAAMC,kBACF;wBACE,cAAc;wBACd,kBAAkB;wBAClB,OAAO;4BACL;gCACE,SAAS;gCACT,QAAQK;gCACR,WAAWvC;gCACX,UAAUM;4BACZ;4BACA;gCACE,SAAS;gCACT,QAAQiC;gCACR,WAAWvC;4BACb;4BACA;gCACE,SAAS;gCACT,QAAQuC;gCACR,WAAWvC;gCACX,UAAUM;4BACZ;yBACD;oBACH,IACA;wBACE,OAAO;4BACL,SAAS;4BACT,QAAQiC;4BACR,WAAWvC;4BACX,UAAU;gCAAC;6BAAE;4BACb,cAAcC;wBAChB;oBACF;oBACJ2C;oBACA,aAAa;wBACX,SAAS;oBACX;oBACA,WAAW;wBACT,SAAS;wBACT,MAAMzC;wBACN,MAAMC;wBACN,OAAO;4BACL,MAAMmC;wBACR;oBACF;gBACF;aACD;QACH,EAAE,OAAM;YACN,OAAO,EAAE;QACX;IACF;IAEA,MAAMa,eAAgB3B,UAAU,QAAQ,IAAwB,EAAE;IAElE,OAAO;QACL,GAAGP,IAAI;QACP,UAAU;eAAIkC;eAAiBrB;SAAS;IAC1C;AACF"}
|
|
1
|
+
{"version":3,"file":"pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.ts"],"sourcesContent":["import type { IAreaChartSpec, IBarChartSpec, ICartesianSeries, ILineChartSpec, IMarkLineSpec } from '@visactor/vchart'\nimport type { AnnotationDifferenceLine, Measure, RegionPadding, VChartSpecPipe } from 'src/types'\nimport { createFormatter, findAllMeasures, autoFormatter } from '../../../../utils'\nimport {\n isDimensionSelector,\n isFieldSelector,\n isMeasureSelector,\n isPartialDatumSelector,\n} from '../../../../../dataSelector'\nimport { isEmpty } from 'remeda'\nimport { ANNOTATION_Z_INDEX } from '../../../../utils/constant'\nimport {\n buildDifferenceCoordinateDatum,\n buildDifferenceText,\n getDifferenceLineStackResolveMode,\n getRuntimeDifferenceValue,\n type ResolvedDifferenceAnchor,\n usesDifferenceLineElementStackEnd,\n resolveDifferenceAnchor,\n} from './annotationDifferenceLineCommon'\n\nconst DEFAULT_LINE_COLOR = '#BCC1CB'\nconst DEFAULT_TEXT_COLOR = '#ffffff'\nconst DEFAULT_TEXT_BACKGROUND_COLOR = '#BCC1CB'\nconst DEFAULT_TEXT_FONT_SIZE = 12\nconst DEFAULT_LINE_WIDTH = 2\nconst DEFAULT_CORNER_RADIUS = 4\nconst DEFAULT_LABEL_PADDING = 4\nconst DEFAULT_END_SYMBOL_SIZE = 12\nconst DEFAULT_END_SYMBOL_REF_X = -4\nconst DEFAULT_GUTTER_BASE_OFFSET = 20\nconst DEFAULT_GUTTER_RIGHT_PADDING = 44\nconst DEFAULT_GUTTER_TOP_PADDING = 36\nconst DEFAULT_BRACKET_LINE_DASH: [number, number] = [2, 2]\nconst DEFAULT_PERCENT_DIFFERENCE_FORMAT = {\n type: 'percent' as const,\n fractionDigits: 2,\n}\n\ntype RegionPaddingObject = Required<Exclude<RegionPadding, number>>\n\nconst getDifferenceLinePath = (index: number, total: number) =>\n total === 1 ? 'annotationDifferenceLine' : `annotationDifferenceLine[${index}]`\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (Array.isArray(value)) {\n return value\n }\n\n return value === undefined || value === null ? [] : [value]\n}\n\nconst normalizeRegionPadding = (padding?: RegionPadding): RegionPaddingObject => {\n if (typeof padding === 'number') {\n return {\n top: padding,\n right: padding,\n bottom: padding,\n left: padding,\n }\n }\n\n return {\n top: padding?.top ?? 0,\n right: padding?.right ?? 0,\n bottom: padding?.bottom ?? 0,\n left: padding?.left ?? 0,\n }\n}\n\nconst mergeDifferenceLineRegionPadding = (\n spec: IBarChartSpec | ILineChartSpec | IAreaChartSpec,\n paddingPatch: Partial<RegionPaddingObject>,\n) => {\n const region = (spec as { region?: Array<Record<string, unknown>> }).region\n\n if (!Array.isArray(region) || region.length === 0) {\n return spec\n }\n\n const mergedPadding = normalizeRegionPadding(region[0].padding as RegionPadding | undefined)\n\n if (paddingPatch.top !== undefined) {\n mergedPadding.top = Math.max(mergedPadding.top, paddingPatch.top)\n }\n\n if (paddingPatch.right !== undefined) {\n mergedPadding.right = Math.max(mergedPadding.right, paddingPatch.right)\n }\n\n if (paddingPatch.bottom !== undefined) {\n mergedPadding.bottom = Math.max(mergedPadding.bottom, paddingPatch.bottom)\n }\n\n if (paddingPatch.left !== undefined) {\n mergedPadding.left = Math.max(mergedPadding.left, paddingPatch.left)\n }\n\n return {\n ...spec,\n region: [\n {\n ...region[0],\n padding: mergedPadding,\n },\n ...region.slice(1),\n ],\n }\n}\n\nconst buildFixedGutterExpandDistance = (isHorizontalChart: boolean) => {\n return (_markerData: unknown, context: any) => {\n const region = context?.region\n const coordinatePoints = Array.isArray(context?.coordinatePoints) ? context.coordinatePoints : []\n\n if (!region || coordinatePoints.length === 0) {\n return 0\n }\n\n const { x: regionStartX, y: regionStartY } = region.getLayoutStartPoint()\n const { width } = region.getLayoutRect()\n\n if (isHorizontalChart) {\n const targetY = regionStartY - DEFAULT_GUTTER_BASE_OFFSET\n const minY = Math.min(...coordinatePoints.map((point: { y: number }) => point.y))\n\n return Math.max(0, minY - targetY)\n }\n\n const targetX = regionStartX + width + DEFAULT_GUTTER_BASE_OFFSET\n const maxX = Math.max(...coordinatePoints.map((point: { x: number }) => point.x))\n\n return Math.max(0, targetX - maxX)\n }\n}\n\nconst getAxisFormatter = (spec: IBarChartSpec | ILineChartSpec | IAreaChartSpec) => {\n const valueAxisOrient = spec.direction === 'horizontal' ? 'bottom' : 'left'\n const formatMethod = spec.axes?.find((axis) => axis.orient === valueAxisOrient)?.label?.formatMethod\n\n return typeof formatMethod === 'function'\n ? (value: number) => String(formatMethod(value as never) ?? value)\n : undefined\n}\n\nconst getExplicitMeasureFormat = (measure?: Measure) => {\n if (measure?.numFormat && !isEmpty(measure.numFormat)) {\n return measure.numFormat\n }\n\n if (measure?.format && !isEmpty(measure.format)) {\n return measure.format\n }\n\n return undefined\n}\n\nconst inferMeasureIdFromDatum = (anchor: ResolvedDifferenceAnchor, measureIds: string[]) => {\n const candidateValues = [anchor.matchedDatum, anchor.coordinateDatum]\n\n for (const datum of candidateValues) {\n if (!datum) {\n continue\n }\n\n const candidates = measureIds.filter((measureId) => Number(datum[measureId]) === anchor.value)\n\n if (candidates.length === 1) {\n return candidates[0]\n }\n }\n\n return undefined\n}\n\nconst inferMeasureIdFromSelector = (\n selectorValue: AnnotationDifferenceLine['start']['selector'],\n measureIdSet: Set<string>,\n) => {\n const matchedMeasureIds = new Set<string>()\n\n for (const currentSelector of toArray(selectorValue)) {\n if (isMeasureSelector(currentSelector)) {\n if (measureIdSet.has(currentSelector.field)) {\n matchedMeasureIds.add(currentSelector.field)\n }\n continue\n }\n\n if (isFieldSelector(currentSelector) || isDimensionSelector(currentSelector)) {\n continue\n }\n\n if (isPartialDatumSelector(currentSelector)) {\n Object.keys(currentSelector).forEach((field) => {\n if (measureIdSet.has(field)) {\n matchedMeasureIds.add(field)\n }\n })\n }\n }\n\n return matchedMeasureIds.size === 1 ? Array.from(matchedMeasureIds)[0] : undefined\n}\n\nconst resolveDifferenceMeasureId = (\n anchor: ResolvedDifferenceAnchor,\n selectorValue: AnnotationDifferenceLine['start']['selector'],\n measureIds: string[],\n) => {\n if (anchor.mode !== 'element') {\n return undefined\n }\n\n if (measureIds.length === 1) {\n return measureIds[0]\n }\n\n const measureIdSet = new Set(measureIds)\n return inferMeasureIdFromSelector(selectorValue, measureIdSet) ?? inferMeasureIdFromDatum(anchor, measureIds)\n}\n\nconst assertDifferenceLineConfig: (value: unknown, path: string) => asserts value is AnnotationDifferenceLine = (\n value,\n path,\n) => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error(`${path} must be an object`)\n }\n\n const start = (value as Record<string, unknown>).start\n if (typeof start !== 'object' || start === null || Array.isArray(start)) {\n throw new Error(`${path}.start is required`)\n }\n if ((start as Record<string, unknown>).selector == null) {\n throw new Error(`${path}.start.selector is required`)\n }\n\n const end = (value as Record<string, unknown>).end\n if (typeof end !== 'object' || end === null || Array.isArray(end)) {\n throw new Error(`${path}.end is required`)\n }\n if ((end as Record<string, unknown>).selector == null) {\n throw new Error(`${path}.end.selector is required`)\n }\n}\n\nexport const annotationDifferenceLine: VChartSpecPipe = (spec, context) => {\n const { advancedVSeed, vseed } = context\n const annotationDifferenceLine = advancedVSeed.annotation?.annotationDifferenceLine\n\n if (!annotationDifferenceLine) {\n return spec\n }\n\n const theme = advancedVSeed.config?.[vseed.chartType as 'column']?.annotation?.annotationDifferenceLine\n const annotationDifferenceLineList = Array.isArray(annotationDifferenceLine)\n ? annotationDifferenceLine\n : [annotationDifferenceLine]\n const dataset = advancedVSeed.dataset.flat()\n const chartSpec = spec as IBarChartSpec | ILineChartSpec | IAreaChartSpec\n const stackResolveMode = getDifferenceLineStackResolveMode(vseed, advancedVSeed)\n const useElementStackEnd = usesDifferenceLineElementStackEnd(vseed, advancedVSeed)\n const isBracketChart = vseed.chartType === 'line' || vseed.chartType === 'area'\n const measures = findAllMeasures(advancedVSeed.measures)\n const measureIds = measures.map((measure) => measure.id)\n const axisFormatter = getAxisFormatter(chartSpec)\n const percentFormatter = createFormatter(DEFAULT_PERCENT_DIFFERENCE_FORMAT)\n const isHorizontalChart = chartSpec.direction === 'horizontal'\n\n const markLine = annotationDifferenceLineList.flatMap((annotationDifferenceLine, index) => {\n try {\n assertDifferenceLineConfig(\n annotationDifferenceLine,\n getDifferenceLinePath(index, annotationDifferenceLineList.length),\n )\n\n const start = resolveDifferenceAnchor({\n dataset,\n selectorLabel: 'start',\n selectorValue: annotationDifferenceLine.start.selector,\n spec: chartSpec,\n stackResolveMode,\n allowSelectorFallback: !useElementStackEnd,\n })\n const end = resolveDifferenceAnchor({\n dataset,\n selectorLabel: 'end',\n selectorValue: annotationDifferenceLine.end.selector,\n spec: chartSpec,\n stackResolveMode,\n allowSelectorFallback: !useElementStackEnd,\n })\n\n if (!start || !end) {\n return []\n }\n\n if (start.mode !== end.mode) {\n return []\n }\n\n const usesRuntimeStackEnd =\n useElementStackEnd ||\n ((vseed.chartType === 'column' || vseed.chartType === 'bar') &&\n start.mode === 'element' &&\n stackResolveMode === 'auto')\n const useBracketStyle =\n isBracketChart ||\n ((vseed.chartType === 'column' || vseed.chartType === 'bar') &&\n start.mode === 'element' &&\n stackResolveMode === 'auto')\n const connectDirection = isHorizontalChart ? 'top' : 'right'\n const expandDistance = buildFixedGutterExpandDistance(isHorizontalChart)\n\n const lineColor = annotationDifferenceLine.lineColor ?? theme?.lineColor ?? DEFAULT_LINE_COLOR\n const textColor = annotationDifferenceLine.textColor ?? theme?.textColor ?? DEFAULT_TEXT_COLOR\n const textBackgroundColor =\n annotationDifferenceLine.textBackgroundColor ?? theme?.textBackgroundColor ?? DEFAULT_TEXT_BACKGROUND_COLOR\n const textFontSize = annotationDifferenceLine.textFontSize ?? theme?.textFontSize ?? DEFAULT_TEXT_FONT_SIZE\n const differenceType = annotationDifferenceLine.differenceType ?? 'absolute'\n const startMeasureId = resolveDifferenceMeasureId(start, annotationDifferenceLine.start.selector, measureIds)\n const endMeasureId = resolveDifferenceMeasureId(end, annotationDifferenceLine.end.selector, measureIds)\n const sameMeasure = startMeasureId !== undefined && startMeasureId === endMeasureId\n const explicitMeasureFormat = sameMeasure\n ? getExplicitMeasureFormat(measures.find((measure) => measure.id === startMeasureId))\n : undefined\n const differenceFormatter =\n differenceType === 'percent'\n ? percentFormatter\n : explicitMeasureFormat\n ? createFormatter(explicitMeasureFormat)\n : (axisFormatter ?? autoFormatter)\n\n const label = usesRuntimeStackEnd\n ? {\n visible: true,\n position: 'middle',\n refY: 0,\n formatMethod: (_markData: any[], seriesData: any[]) => {\n try {\n return buildDifferenceText(\n getRuntimeDifferenceValue({\n anchor: start,\n seriesData,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n getRuntimeDifferenceValue({\n anchor: end,\n seriesData,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n differenceType,\n differenceFormatter,\n )\n } catch {\n return ''\n }\n },\n style: {\n fill: textColor,\n fontSize: textFontSize,\n },\n labelBackground: {\n visible: true,\n padding: DEFAULT_LABEL_PADDING,\n style: {\n fill: textBackgroundColor,\n fillOpacity: 1,\n stroke: lineColor,\n lineWidth: 1,\n cornerRadius: DEFAULT_CORNER_RADIUS,\n },\n },\n }\n : {\n visible: true,\n position: 'middle',\n refY: 0,\n text: buildDifferenceText(start.value, end.value, differenceType, differenceFormatter),\n style: {\n fill: textColor,\n fontSize: textFontSize,\n },\n labelBackground: {\n visible: true,\n padding: DEFAULT_LABEL_PADDING,\n style: {\n fill: textBackgroundColor,\n fillOpacity: 1,\n stroke: lineColor,\n lineWidth: 1,\n cornerRadius: DEFAULT_CORNER_RADIUS,\n },\n },\n }\n\n return [\n {\n type: 'type-step',\n autoRange: true,\n zIndex: ANNOTATION_Z_INDEX,\n connectDirection,\n expandDistance,\n coordinates: (seriesData: any[], relativeSeries: ICartesianSeries) => {\n try {\n return [\n buildDifferenceCoordinateDatum({\n anchor: start,\n seriesData,\n relativeSeries,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n buildDifferenceCoordinateDatum({\n anchor: end,\n seriesData,\n relativeSeries,\n useElementStackEnd: usesRuntimeStackEnd,\n }),\n ]\n } catch {\n return []\n }\n },\n line: useBracketStyle\n ? {\n multiSegment: true,\n mainSegmentIndex: 1,\n style: [\n {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n lineDash: DEFAULT_BRACKET_LINE_DASH,\n },\n {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n },\n {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n lineDash: DEFAULT_BRACKET_LINE_DASH,\n },\n ],\n }\n : {\n style: {\n visible: true,\n stroke: lineColor,\n lineWidth: DEFAULT_LINE_WIDTH,\n lineDash: [0],\n cornerRadius: DEFAULT_CORNER_RADIUS,\n },\n },\n label,\n startSymbol: {\n visible: false,\n },\n endSymbol: {\n visible: true,\n size: DEFAULT_END_SYMBOL_SIZE,\n refX: DEFAULT_END_SYMBOL_REF_X,\n style: {\n fill: lineColor,\n },\n },\n } as IMarkLineSpec,\n ]\n } catch {\n return []\n }\n })\n\n const specMarkLine = (chartSpec.markLine as IMarkLineSpec[]) || []\n const nextSpec = {\n ...spec,\n markLine: [...specMarkLine, ...markLine],\n }\n\n if (markLine.length === 0) {\n return nextSpec\n }\n\n return mergeDifferenceLineRegionPadding(\n nextSpec as IBarChartSpec | ILineChartSpec | IAreaChartSpec,\n isHorizontalChart ? { top: DEFAULT_GUTTER_TOP_PADDING } : { right: DEFAULT_GUTTER_RIGHT_PADDING },\n )\n}\n"],"names":["DEFAULT_LINE_COLOR","DEFAULT_TEXT_COLOR","DEFAULT_TEXT_BACKGROUND_COLOR","DEFAULT_TEXT_FONT_SIZE","DEFAULT_LINE_WIDTH","DEFAULT_CORNER_RADIUS","DEFAULT_LABEL_PADDING","DEFAULT_END_SYMBOL_SIZE","DEFAULT_END_SYMBOL_REF_X","DEFAULT_GUTTER_BASE_OFFSET","DEFAULT_GUTTER_RIGHT_PADDING","DEFAULT_GUTTER_TOP_PADDING","DEFAULT_BRACKET_LINE_DASH","DEFAULT_PERCENT_DIFFERENCE_FORMAT","getDifferenceLinePath","index","total","toArray","value","Array","normalizeRegionPadding","padding","mergeDifferenceLineRegionPadding","spec","paddingPatch","region","mergedPadding","undefined","Math","buildFixedGutterExpandDistance","isHorizontalChart","_markerData","context","coordinatePoints","regionStartX","regionStartY","width","targetY","minY","point","targetX","maxX","getAxisFormatter","valueAxisOrient","formatMethod","axis","String","getExplicitMeasureFormat","measure","isEmpty","inferMeasureIdFromDatum","anchor","measureIds","candidateValues","datum","candidates","measureId","Number","inferMeasureIdFromSelector","selectorValue","measureIdSet","matchedMeasureIds","Set","currentSelector","isMeasureSelector","isFieldSelector","isDimensionSelector","isPartialDatumSelector","Object","field","resolveDifferenceMeasureId","assertDifferenceLineConfig","path","Error","start","end","annotationDifferenceLine","advancedVSeed","vseed","theme","annotationDifferenceLineList","dataset","chartSpec","stackResolveMode","getDifferenceLineStackResolveMode","useElementStackEnd","usesDifferenceLineElementStackEnd","isBracketChart","measures","findAllMeasures","axisFormatter","percentFormatter","createFormatter","markLine","resolveDifferenceAnchor","usesRuntimeStackEnd","useBracketStyle","connectDirection","expandDistance","lineColor","textColor","textBackgroundColor","textFontSize","differenceType","startMeasureId","endMeasureId","sameMeasure","explicitMeasureFormat","differenceFormatter","autoFormatter","label","_markData","seriesData","buildDifferenceText","getRuntimeDifferenceValue","ANNOTATION_Z_INDEX","relativeSeries","buildDifferenceCoordinateDatum","specMarkLine","nextSpec"],"mappings":"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"}
|
|
@@ -36,7 +36,8 @@ export declare const getRuntimeDifferenceValue: (options: {
|
|
|
36
36
|
seriesData: Datum[];
|
|
37
37
|
useElementStackEnd?: boolean;
|
|
38
38
|
}) => number;
|
|
39
|
-
export declare const
|
|
39
|
+
export declare const getDifferenceValue: (startValue: number, endValue: number, differenceType?: "absolute" | "percent") => number;
|
|
40
|
+
export declare const buildDifferenceText: (startValue: number, endValue: number, differenceType?: "absolute" | "percent", formatter?: (value: number) => string) => string;
|
|
40
41
|
export declare const inferDifferenceConnectDirection: (vseed: VSeed, values: [number, number]) => "left" | "top" | "right" | "bottom";
|
|
41
42
|
export declare const inferDifferenceBracketDirection: (start: ResolvedDifferenceAnchor, end: ResolvedDifferenceAnchor) => "left" | "right";
|
|
42
43
|
export {};
|
|
@@ -157,8 +157,9 @@ const resolveDifferenceAnchor = (options)=>{
|
|
|
157
157
|
};
|
|
158
158
|
};
|
|
159
159
|
const getStackRuntimeTotal = (runtimeMatches)=>{
|
|
160
|
+
if (0 === runtimeMatches.length) return;
|
|
160
161
|
const stackEndValues = runtimeMatches.map((datum)=>Number(datum[STACK_END_FIELD]));
|
|
161
|
-
if (stackEndValues.some((value)
|
|
162
|
+
if (stackEndValues.some((value)=>!Number.isFinite(value))) return;
|
|
162
163
|
if (hasMixedSigns(stackEndValues)) throw new Error('annotationDifferenceLine does not support mixed-sign runtime stack totals in v1');
|
|
163
164
|
return stackEndValues.some((value)=>value < 0) ? Math.min(...stackEndValues) : Math.max(...stackEndValues);
|
|
164
165
|
};
|
|
@@ -171,7 +172,7 @@ const buildDifferenceCoordinateDatum = (options)=>{
|
|
|
171
172
|
const runtimeStackEnd = Number(runtimeMatch?.[STACK_END_FIELD]);
|
|
172
173
|
return {
|
|
173
174
|
...runtimeMatch ?? anchor.coordinateDatum,
|
|
174
|
-
[relativeSeries.getStackValueField()]: Number.
|
|
175
|
+
[relativeSeries.getStackValueField()]: Number.isFinite(runtimeStackEnd) ? runtimeStackEnd : anchor.value
|
|
175
176
|
};
|
|
176
177
|
}
|
|
177
178
|
const runtimeMatches = seriesData.filter((datum)=>isSubset(anchor.stackGroupDatum, datum));
|
|
@@ -190,14 +191,20 @@ const getRuntimeDifferenceValue = (options)=>{
|
|
|
190
191
|
if (!useElementStackEnd || !anchor.matchedDatum) return anchor.value;
|
|
191
192
|
const runtimeMatch = seriesData.find((datum)=>isSubset(anchor.matchedDatum, datum));
|
|
192
193
|
const runtimeStackEnd = Number(runtimeMatch?.[STACK_END_FIELD]);
|
|
193
|
-
return Number.
|
|
194
|
+
return Number.isFinite(runtimeStackEnd) ? runtimeStackEnd : anchor.value;
|
|
194
195
|
};
|
|
195
|
-
const
|
|
196
|
+
const getDifferenceValue = (startValue, endValue, differenceType = 'absolute')=>{
|
|
196
197
|
if ('percent' === differenceType) {
|
|
197
198
|
if (0 === startValue) throw new Error('annotationDifferenceLine percent difference cannot be computed because start value is 0');
|
|
198
|
-
return
|
|
199
|
+
return (endValue - startValue) / startValue;
|
|
199
200
|
}
|
|
200
|
-
return
|
|
201
|
+
return endValue - startValue;
|
|
202
|
+
};
|
|
203
|
+
const buildDifferenceText = (startValue, endValue, differenceType = 'absolute', formatter)=>{
|
|
204
|
+
const differenceValue = getDifferenceValue(startValue, endValue, differenceType);
|
|
205
|
+
if (formatter) return formatter(differenceValue);
|
|
206
|
+
if ('percent' === differenceType) return `${(100 * differenceValue).toFixed(2)}%`;
|
|
207
|
+
return `${differenceValue}`;
|
|
201
208
|
};
|
|
202
209
|
const inferDifferenceConnectDirection = (vseed, values)=>{
|
|
203
210
|
const isNegativeSide = values.every((value)=>value < 0);
|
|
@@ -208,6 +215,6 @@ const inferDifferenceBracketDirection = (start, end)=>{
|
|
|
208
215
|
if (void 0 === start.bandIndex || void 0 === end.bandIndex) return 'right';
|
|
209
216
|
return start.bandIndex <= end.bandIndex ? 'right' : 'left';
|
|
210
217
|
};
|
|
211
|
-
export { buildDifferenceCoordinateDatum, buildDifferenceText, getDifferenceLineStackResolveMode, getRuntimeDifferenceValue, getStackRuntimeTotal, inferDifferenceBracketDirection, inferDifferenceConnectDirection, resolveDifferenceAnchor, usesDifferenceLineElementStackEnd };
|
|
218
|
+
export { buildDifferenceCoordinateDatum, buildDifferenceText, getDifferenceLineStackResolveMode, getDifferenceValue, getRuntimeDifferenceValue, getStackRuntimeTotal, inferDifferenceBracketDirection, inferDifferenceConnectDirection, resolveDifferenceAnchor, usesDifferenceLineElementStackEnd };
|
|
212
219
|
|
|
213
220
|
//# sourceMappingURL=annotationDifferenceLineCommon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.ts"],"sourcesContent":["import type { IAreaChartSpec, IBarChartSpec, ICartesianSeries, ILineChartSpec } from '@visactor/vchart'\nimport {\n isDimensionSelector,\n isFieldSelector,\n isMeasureSelector,\n isPartialDatumSelector,\n isValueSelector,\n selector,\n} from '../../../../../dataSelector'\nimport { hasMultipleMeasureInSingleView, isBarLikeChart } from 'src/pipeline/utils'\nimport type { AdvancedVSeed, Datum, Selector, Selectors, VSeed } from 'src/types'\nimport { isSubset } from './utils'\n\ntype DifferenceSelectorLabel = 'start' | 'end'\ntype DifferenceChartSpec = IBarChartSpec | ILineChartSpec | IAreaChartSpec\nexport type DifferenceStackResolveMode = 'none' | 'stackTotal' | 'auto'\nexport type DifferenceAnchorMode = 'element' | 'stackTotal'\n\nexport type ResolvedDifferenceAnchor = {\n mode: DifferenceAnchorMode\n selectorLabel: DifferenceSelectorLabel\n coordinateDatum: Datum\n matchedDatum?: Datum\n stackGroupDatum?: Datum\n bandDatum: Datum\n bandIndex?: number\n value: number\n}\n\nconst STACK_END_FIELD = '__VCHART_STACK_END'\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (Array.isArray(value)) {\n return value\n }\n\n return value === undefined || value === null ? [] : [value]\n}\n\nconst getDifferenceBandFields = (spec: DifferenceChartSpec): string[] => {\n return toArray((spec.direction === 'horizontal' ? spec.yField : spec.xField) as string | string[] | undefined)\n}\n\nconst getDifferenceValueField = (spec: DifferenceChartSpec): string => {\n const valueField = toArray(\n (spec.direction === 'horizontal' ? spec.xField : spec.yField) as string | string[] | undefined,\n )[0]\n\n if (!valueField) {\n throw new Error('annotationDifferenceLine requires a value field in the target chart spec')\n }\n\n return valueField\n}\n\nconst normalizeDifferenceValue = (value: unknown, selectorLabel: DifferenceSelectorLabel, field: string): number => {\n const numberValue = Number(value)\n\n if (Number.isNaN(numberValue)) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector resolved to a non-numeric value on field \"${field}\"`,\n )\n }\n\n return numberValue\n}\n\nconst buildStackGroupDatum = (datum: Datum, bandFields: string[]) => {\n return Object.fromEntries(bandFields.map((field) => [field, datum[field]])) as Datum\n}\n\nconst resolveBandIndex = (dataset: Datum[], bandDatum: Datum) => {\n const bandIndex = dataset.findIndex((datum) => isSubset(bandDatum, datum))\n\n return bandIndex >= 0 ? bandIndex : undefined\n}\n\nconst buildFallbackSelectorDatum = (selectorValue: Selector | Selectors): Datum | undefined => {\n const selectorList = Array.isArray(selectorValue) ? selectorValue : [selectorValue]\n const fallbackDatum: Datum = {}\n\n for (const currentSelector of selectorList) {\n if (isValueSelector(currentSelector) || isFieldSelector(currentSelector)) {\n return undefined\n }\n\n if (isMeasureSelector(currentSelector)) {\n const operator = currentSelector.operator || currentSelector.op\n const selectorValues = Array.isArray(currentSelector.value) ? currentSelector.value : [currentSelector.value]\n\n if (!['=', '=='].includes(operator as string) || selectorValues.length !== 1) {\n return undefined\n }\n\n fallbackDatum[currentSelector.field] = selectorValues[0]\n continue\n }\n\n if (isDimensionSelector(currentSelector)) {\n const operator = currentSelector.operator || currentSelector.op\n const selectorValues = Array.isArray(currentSelector.value) ? currentSelector.value : [currentSelector.value]\n\n if (operator !== 'in' || selectorValues.length !== 1) {\n return undefined\n }\n\n fallbackDatum[currentSelector.field] = selectorValues[0]\n continue\n }\n\n if (isPartialDatumSelector(currentSelector)) {\n Object.assign(fallbackDatum, currentSelector)\n continue\n }\n\n return undefined\n }\n\n return Object.keys(fallbackDatum).length > 0 ? fallbackDatum : undefined\n}\n\nconst inferFallbackValue = (fallbackDatum: Datum, valueField: string, bandFields: string[]) => {\n if (valueField in fallbackDatum) {\n return fallbackDatum[valueField]\n }\n\n const numericCandidateKeys = Object.keys(fallbackDatum).filter((key) => {\n if (key === valueField || bandFields.includes(key)) {\n return false\n }\n\n return typeof fallbackDatum[key] === 'number'\n })\n\n if (numericCandidateKeys.length !== 1) {\n return undefined\n }\n\n return fallbackDatum[numericCandidateKeys[0]]\n}\n\nconst resolveFallbackAnchor = (options: {\n dataset: Datum[]\n selectorLabel: DifferenceSelectorLabel\n selectorValue: Selector | Selectors\n valueField: string\n bandFields: string[]\n}): ResolvedDifferenceAnchor | undefined => {\n const { dataset, selectorLabel, selectorValue, valueField, bandFields } = options\n const fallbackDatum = buildFallbackSelectorDatum(selectorValue)\n\n if (!fallbackDatum) {\n return undefined\n }\n\n const inferredValue = inferFallbackValue(fallbackDatum, valueField, bandFields)\n\n if (inferredValue === undefined) {\n return undefined\n }\n\n const coordinateDatum = {\n ...fallbackDatum,\n [valueField]: inferredValue,\n }\n const bandDatum = buildStackGroupDatum(coordinateDatum, bandFields)\n\n try {\n return {\n mode: 'element',\n selectorLabel,\n coordinateDatum,\n matchedDatum: fallbackDatum,\n bandDatum,\n bandIndex: resolveBandIndex(dataset, bandDatum),\n value: normalizeDifferenceValue(inferredValue, selectorLabel, valueField),\n }\n } catch {\n return undefined\n }\n}\n\nconst hasMixedSigns = (values: number[]) => {\n const nonZeroValues = values.filter((value) => value !== 0)\n\n return nonZeroValues.some((value) => value > 0) && nonZeroValues.some((value) => value < 0)\n}\n\nexport const getDifferenceLineStackResolveMode = (\n vseed: VSeed,\n advancedVSeed: AdvancedVSeed,\n): DifferenceStackResolveMode => {\n const hasMultipleMeasure = hasMultipleMeasureInSingleView(advancedVSeed.reshapeMeasures ?? [])\n\n if (!hasMultipleMeasure) {\n return 'none'\n }\n\n if (vseed.chartType === 'column') {\n return 'auto'\n }\n\n if (vseed.chartType === 'bar') {\n return 'auto'\n }\n\n return 'none'\n}\n\nexport const usesDifferenceLineElementStackEnd = (vseed: VSeed, advancedVSeed: AdvancedVSeed) => {\n return vseed.chartType === 'area' && hasMultipleMeasureInSingleView(advancedVSeed.reshapeMeasures ?? [])\n}\n\nexport const resolveDifferenceAnchor = (options: {\n dataset: Datum[]\n selectorLabel: DifferenceSelectorLabel\n selectorValue: Selector | Selectors\n spec: DifferenceChartSpec\n stackResolveMode: DifferenceStackResolveMode\n allowSelectorFallback?: boolean\n}): ResolvedDifferenceAnchor | undefined => {\n const { dataset, selectorLabel, selectorValue, spec, stackResolveMode, allowSelectorFallback = true } = options\n const matches = dataset.filter((datum) => selector(datum, selectorValue))\n const valueField = getDifferenceValueField(spec)\n const bandFields = getDifferenceBandFields(spec)\n\n if (matches.length === 0) {\n return stackResolveMode === 'none' && allowSelectorFallback\n ? resolveFallbackAnchor({ dataset, selectorLabel, selectorValue, valueField, bandFields })\n : undefined\n }\n\n if (stackResolveMode === 'none' || (stackResolveMode === 'auto' && matches.length === 1)) {\n if (matches.length !== 1) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector must resolve to exactly one datum, got ${matches.length}`,\n )\n }\n\n const bandDatum = buildStackGroupDatum(matches[0], bandFields)\n\n return {\n mode: 'element',\n selectorLabel,\n coordinateDatum: matches[0],\n matchedDatum: matches[0],\n bandDatum,\n bandIndex: resolveBandIndex(dataset, bandDatum),\n value: normalizeDifferenceValue(matches[0][valueField], selectorLabel, valueField),\n }\n }\n const stackGroups = new Map<string, Datum>()\n\n matches.forEach((datum) => {\n const stackGroupDatum = buildStackGroupDatum(datum, bandFields)\n stackGroups.set(JSON.stringify(stackGroupDatum), stackGroupDatum)\n })\n\n if (stackGroups.size !== 1) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector must resolve to exactly one stack group, got ${stackGroups.size}`,\n )\n }\n\n const stackGroupDatum = Array.from(stackGroups.values())[0]\n const groupRows = dataset.filter((datum) => isSubset(stackGroupDatum, datum))\n\n if (stackResolveMode === 'auto' && groupRows.length !== matches.length) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector must resolve to exactly one stack element or one full stack group`,\n )\n }\n const groupValues = groupRows.map((datum) => normalizeDifferenceValue(datum[valueField], selectorLabel, valueField))\n\n if (hasMixedSigns(groupValues)) {\n throw new Error('annotationDifferenceLine does not support mixed-sign stack totals in v1')\n }\n\n return {\n mode: 'stackTotal',\n selectorLabel,\n coordinateDatum: stackGroupDatum,\n matchedDatum: matches[0],\n stackGroupDatum,\n bandDatum: stackGroupDatum,\n bandIndex: resolveBandIndex(dataset, stackGroupDatum),\n value: groupValues.reduce((sum, value) => sum + value, 0),\n }\n}\n\nexport const getStackRuntimeTotal = (runtimeMatches: Datum[]) => {\n const stackEndValues = runtimeMatches.map((datum) => Number(datum[STACK_END_FIELD]))\n\n if (stackEndValues.some((value) => Number.isNaN(value))) {\n return undefined\n }\n\n if (hasMixedSigns(stackEndValues)) {\n throw new Error('annotationDifferenceLine does not support mixed-sign runtime stack totals in v1')\n }\n\n return stackEndValues.some((value) => value < 0) ? Math.min(...stackEndValues) : Math.max(...stackEndValues)\n}\n\nexport const buildDifferenceCoordinateDatum = (options: {\n anchor: ResolvedDifferenceAnchor\n seriesData: Datum[]\n relativeSeries: ICartesianSeries\n useElementStackEnd?: boolean\n}) => {\n const { anchor, seriesData, relativeSeries, useElementStackEnd = false } = options\n\n if (!anchor.stackGroupDatum) {\n const runtimeMatches = anchor.matchedDatum\n ? seriesData.filter((datum) => isSubset(anchor.matchedDatum as Datum, datum))\n : []\n\n if (!useElementStackEnd) {\n return runtimeMatches[0] ?? anchor.coordinateDatum\n }\n\n const runtimeMatch = runtimeMatches[0]\n const runtimeStackEnd = Number(runtimeMatch?.[STACK_END_FIELD])\n\n return {\n ...(runtimeMatch ?? anchor.coordinateDatum),\n [relativeSeries.getStackValueField()]: Number.isNaN(runtimeStackEnd) ? anchor.value : runtimeStackEnd,\n }\n }\n\n const runtimeMatches = seriesData.filter((datum) => isSubset(anchor.stackGroupDatum as Datum, datum))\n const runtimeStackTotal = getStackRuntimeTotal(runtimeMatches)\n\n return {\n ...(runtimeMatches[0] ?? anchor.coordinateDatum),\n [relativeSeries.getStackValueField()]: runtimeStackTotal ?? anchor.value,\n }\n}\n\nexport const getRuntimeDifferenceValue = (options: {\n anchor: ResolvedDifferenceAnchor\n seriesData: Datum[]\n useElementStackEnd?: boolean\n}) => {\n const { anchor, seriesData, useElementStackEnd = false } = options\n\n if (anchor.stackGroupDatum) {\n const runtimeMatches = seriesData.filter((datum) => isSubset(anchor.stackGroupDatum as Datum, datum))\n return getStackRuntimeTotal(runtimeMatches) ?? anchor.value\n }\n\n if (!useElementStackEnd || !anchor.matchedDatum) {\n return anchor.value\n }\n\n const runtimeMatch = seriesData.find((datum) => isSubset(anchor.matchedDatum as Datum, datum))\n const runtimeStackEnd = Number(runtimeMatch?.[STACK_END_FIELD])\n\n return Number.isNaN(runtimeStackEnd) ? anchor.value : runtimeStackEnd\n}\n\nexport const buildDifferenceText = (\n startValue: number,\n endValue: number,\n differenceType: 'absolute' | 'percent' = 'absolute',\n) => {\n if (differenceType === 'percent') {\n if (startValue === 0) {\n throw new Error('annotationDifferenceLine percent difference cannot be computed because start value is 0')\n }\n\n return `${(((endValue - startValue) / startValue) * 100).toFixed(0)}%`\n }\n\n return `${endValue - startValue}`\n}\n\nexport const inferDifferenceConnectDirection = (vseed: VSeed, values: [number, number]) => {\n const isNegativeSide = values.every((value) => value < 0)\n\n if (isBarLikeChart(vseed)) {\n return isNegativeSide ? 'left' : 'right'\n }\n\n return isNegativeSide ? 'bottom' : 'top'\n}\n\nexport const inferDifferenceBracketDirection = (\n start: ResolvedDifferenceAnchor,\n end: ResolvedDifferenceAnchor,\n): 'left' | 'right' => {\n if (start.bandIndex === undefined || end.bandIndex === undefined) {\n return 'right'\n }\n\n return start.bandIndex <= end.bandIndex ? 'right' : 'left'\n}\n"],"names":["STACK_END_FIELD","toArray","value","Array","getDifferenceBandFields","spec","getDifferenceValueField","valueField","Error","normalizeDifferenceValue","selectorLabel","field","numberValue","Number","buildStackGroupDatum","datum","bandFields","Object","resolveBandIndex","dataset","bandDatum","bandIndex","isSubset","undefined","buildFallbackSelectorDatum","selectorValue","selectorList","fallbackDatum","currentSelector","isValueSelector","isFieldSelector","isMeasureSelector","operator","selectorValues","isDimensionSelector","isPartialDatumSelector","inferFallbackValue","numericCandidateKeys","key","resolveFallbackAnchor","options","inferredValue","coordinateDatum","hasMixedSigns","values","nonZeroValues","getDifferenceLineStackResolveMode","vseed","advancedVSeed","hasMultipleMeasure","hasMultipleMeasureInSingleView","usesDifferenceLineElementStackEnd","resolveDifferenceAnchor","stackResolveMode","allowSelectorFallback","matches","selector","stackGroups","Map","stackGroupDatum","JSON","groupRows","groupValues","sum","getStackRuntimeTotal","runtimeMatches","stackEndValues","Math","buildDifferenceCoordinateDatum","anchor","seriesData","relativeSeries","useElementStackEnd","runtimeMatch","runtimeStackEnd","runtimeStackTotal","getRuntimeDifferenceValue","buildDifferenceText","startValue","endValue","differenceType","inferDifferenceConnectDirection","isNegativeSide","isBarLikeChart","inferDifferenceBracketDirection","start","end"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/annotation/annotationDifferenceLineCommon.ts"],"sourcesContent":["import type { IAreaChartSpec, IBarChartSpec, ICartesianSeries, ILineChartSpec } from '@visactor/vchart'\nimport {\n isDimensionSelector,\n isFieldSelector,\n isMeasureSelector,\n isPartialDatumSelector,\n isValueSelector,\n selector,\n} from '../../../../../dataSelector'\nimport { hasMultipleMeasureInSingleView, isBarLikeChart } from 'src/pipeline/utils'\nimport type { AdvancedVSeed, Datum, Selector, Selectors, VSeed } from 'src/types'\nimport { isSubset } from './utils'\n\ntype DifferenceSelectorLabel = 'start' | 'end'\ntype DifferenceChartSpec = IBarChartSpec | ILineChartSpec | IAreaChartSpec\nexport type DifferenceStackResolveMode = 'none' | 'stackTotal' | 'auto'\nexport type DifferenceAnchorMode = 'element' | 'stackTotal'\n\nexport type ResolvedDifferenceAnchor = {\n mode: DifferenceAnchorMode\n selectorLabel: DifferenceSelectorLabel\n coordinateDatum: Datum\n matchedDatum?: Datum\n stackGroupDatum?: Datum\n bandDatum: Datum\n bandIndex?: number\n value: number\n}\n\nconst STACK_END_FIELD = '__VCHART_STACK_END'\n\nconst toArray = <T>(value: T | T[] | undefined | null): T[] => {\n if (Array.isArray(value)) {\n return value\n }\n\n return value === undefined || value === null ? [] : [value]\n}\n\nconst getDifferenceBandFields = (spec: DifferenceChartSpec): string[] => {\n return toArray((spec.direction === 'horizontal' ? spec.yField : spec.xField) as string | string[] | undefined)\n}\n\nconst getDifferenceValueField = (spec: DifferenceChartSpec): string => {\n const valueField = toArray(\n (spec.direction === 'horizontal' ? spec.xField : spec.yField) as string | string[] | undefined,\n )[0]\n\n if (!valueField) {\n throw new Error('annotationDifferenceLine requires a value field in the target chart spec')\n }\n\n return valueField\n}\n\nconst normalizeDifferenceValue = (value: unknown, selectorLabel: DifferenceSelectorLabel, field: string): number => {\n const numberValue = Number(value)\n\n if (Number.isNaN(numberValue)) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector resolved to a non-numeric value on field \"${field}\"`,\n )\n }\n\n return numberValue\n}\n\nconst buildStackGroupDatum = (datum: Datum, bandFields: string[]) => {\n return Object.fromEntries(bandFields.map((field) => [field, datum[field]])) as Datum\n}\n\nconst resolveBandIndex = (dataset: Datum[], bandDatum: Datum) => {\n const bandIndex = dataset.findIndex((datum) => isSubset(bandDatum, datum))\n\n return bandIndex >= 0 ? bandIndex : undefined\n}\n\nconst buildFallbackSelectorDatum = (selectorValue: Selector | Selectors): Datum | undefined => {\n const selectorList = Array.isArray(selectorValue) ? selectorValue : [selectorValue]\n const fallbackDatum: Datum = {}\n\n for (const currentSelector of selectorList) {\n if (isValueSelector(currentSelector) || isFieldSelector(currentSelector)) {\n return undefined\n }\n\n if (isMeasureSelector(currentSelector)) {\n const operator = currentSelector.operator || currentSelector.op\n const selectorValues = Array.isArray(currentSelector.value) ? currentSelector.value : [currentSelector.value]\n\n if (!['=', '=='].includes(operator as string) || selectorValues.length !== 1) {\n return undefined\n }\n\n fallbackDatum[currentSelector.field] = selectorValues[0]\n continue\n }\n\n if (isDimensionSelector(currentSelector)) {\n const operator = currentSelector.operator || currentSelector.op\n const selectorValues = Array.isArray(currentSelector.value) ? currentSelector.value : [currentSelector.value]\n\n if (operator !== 'in' || selectorValues.length !== 1) {\n return undefined\n }\n\n fallbackDatum[currentSelector.field] = selectorValues[0]\n continue\n }\n\n if (isPartialDatumSelector(currentSelector)) {\n Object.assign(fallbackDatum, currentSelector)\n continue\n }\n\n return undefined\n }\n\n return Object.keys(fallbackDatum).length > 0 ? fallbackDatum : undefined\n}\n\nconst inferFallbackValue = (fallbackDatum: Datum, valueField: string, bandFields: string[]) => {\n if (valueField in fallbackDatum) {\n return fallbackDatum[valueField]\n }\n\n const numericCandidateKeys = Object.keys(fallbackDatum).filter((key) => {\n if (key === valueField || bandFields.includes(key)) {\n return false\n }\n\n return typeof fallbackDatum[key] === 'number'\n })\n\n if (numericCandidateKeys.length !== 1) {\n return undefined\n }\n\n return fallbackDatum[numericCandidateKeys[0]]\n}\n\nconst resolveFallbackAnchor = (options: {\n dataset: Datum[]\n selectorLabel: DifferenceSelectorLabel\n selectorValue: Selector | Selectors\n valueField: string\n bandFields: string[]\n}): ResolvedDifferenceAnchor | undefined => {\n const { dataset, selectorLabel, selectorValue, valueField, bandFields } = options\n const fallbackDatum = buildFallbackSelectorDatum(selectorValue)\n\n if (!fallbackDatum) {\n return undefined\n }\n\n const inferredValue = inferFallbackValue(fallbackDatum, valueField, bandFields)\n\n if (inferredValue === undefined) {\n return undefined\n }\n\n const coordinateDatum = {\n ...fallbackDatum,\n [valueField]: inferredValue,\n }\n const bandDatum = buildStackGroupDatum(coordinateDatum, bandFields)\n\n try {\n return {\n mode: 'element',\n selectorLabel,\n coordinateDatum,\n matchedDatum: fallbackDatum,\n bandDatum,\n bandIndex: resolveBandIndex(dataset, bandDatum),\n value: normalizeDifferenceValue(inferredValue, selectorLabel, valueField),\n }\n } catch {\n return undefined\n }\n}\n\nconst hasMixedSigns = (values: number[]) => {\n const nonZeroValues = values.filter((value) => value !== 0)\n\n return nonZeroValues.some((value) => value > 0) && nonZeroValues.some((value) => value < 0)\n}\n\nexport const getDifferenceLineStackResolveMode = (\n vseed: VSeed,\n advancedVSeed: AdvancedVSeed,\n): DifferenceStackResolveMode => {\n const hasMultipleMeasure = hasMultipleMeasureInSingleView(advancedVSeed.reshapeMeasures ?? [])\n\n if (!hasMultipleMeasure) {\n return 'none'\n }\n\n if (vseed.chartType === 'column') {\n return 'auto'\n }\n\n if (vseed.chartType === 'bar') {\n return 'auto'\n }\n\n return 'none'\n}\n\nexport const usesDifferenceLineElementStackEnd = (vseed: VSeed, advancedVSeed: AdvancedVSeed) => {\n return vseed.chartType === 'area' && hasMultipleMeasureInSingleView(advancedVSeed.reshapeMeasures ?? [])\n}\n\nexport const resolveDifferenceAnchor = (options: {\n dataset: Datum[]\n selectorLabel: DifferenceSelectorLabel\n selectorValue: Selector | Selectors\n spec: DifferenceChartSpec\n stackResolveMode: DifferenceStackResolveMode\n allowSelectorFallback?: boolean\n}): ResolvedDifferenceAnchor | undefined => {\n const { dataset, selectorLabel, selectorValue, spec, stackResolveMode, allowSelectorFallback = true } = options\n const matches = dataset.filter((datum) => selector(datum, selectorValue))\n const valueField = getDifferenceValueField(spec)\n const bandFields = getDifferenceBandFields(spec)\n\n if (matches.length === 0) {\n return stackResolveMode === 'none' && allowSelectorFallback\n ? resolveFallbackAnchor({ dataset, selectorLabel, selectorValue, valueField, bandFields })\n : undefined\n }\n\n if (stackResolveMode === 'none' || (stackResolveMode === 'auto' && matches.length === 1)) {\n if (matches.length !== 1) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector must resolve to exactly one datum, got ${matches.length}`,\n )\n }\n\n const bandDatum = buildStackGroupDatum(matches[0], bandFields)\n\n return {\n mode: 'element',\n selectorLabel,\n coordinateDatum: matches[0],\n matchedDatum: matches[0],\n bandDatum,\n bandIndex: resolveBandIndex(dataset, bandDatum),\n value: normalizeDifferenceValue(matches[0][valueField], selectorLabel, valueField),\n }\n }\n const stackGroups = new Map<string, Datum>()\n\n matches.forEach((datum) => {\n const stackGroupDatum = buildStackGroupDatum(datum, bandFields)\n stackGroups.set(JSON.stringify(stackGroupDatum), stackGroupDatum)\n })\n\n if (stackGroups.size !== 1) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector must resolve to exactly one stack group, got ${stackGroups.size}`,\n )\n }\n\n const stackGroupDatum = Array.from(stackGroups.values())[0]\n const groupRows = dataset.filter((datum) => isSubset(stackGroupDatum, datum))\n\n if (stackResolveMode === 'auto' && groupRows.length !== matches.length) {\n throw new Error(\n `annotationDifferenceLine ${selectorLabel} selector must resolve to exactly one stack element or one full stack group`,\n )\n }\n const groupValues = groupRows.map((datum) => normalizeDifferenceValue(datum[valueField], selectorLabel, valueField))\n\n if (hasMixedSigns(groupValues)) {\n throw new Error('annotationDifferenceLine does not support mixed-sign stack totals in v1')\n }\n\n return {\n mode: 'stackTotal',\n selectorLabel,\n coordinateDatum: stackGroupDatum,\n matchedDatum: matches[0],\n stackGroupDatum,\n bandDatum: stackGroupDatum,\n bandIndex: resolveBandIndex(dataset, stackGroupDatum),\n value: groupValues.reduce((sum, value) => sum + value, 0),\n }\n}\n\nexport const getStackRuntimeTotal = (runtimeMatches: Datum[]) => {\n if (runtimeMatches.length === 0) {\n return undefined\n }\n\n const stackEndValues = runtimeMatches.map((datum) => Number(datum[STACK_END_FIELD]))\n\n if (stackEndValues.some((value) => !Number.isFinite(value))) {\n return undefined\n }\n\n if (hasMixedSigns(stackEndValues)) {\n throw new Error('annotationDifferenceLine does not support mixed-sign runtime stack totals in v1')\n }\n\n return stackEndValues.some((value) => value < 0) ? Math.min(...stackEndValues) : Math.max(...stackEndValues)\n}\n\nexport const buildDifferenceCoordinateDatum = (options: {\n anchor: ResolvedDifferenceAnchor\n seriesData: Datum[]\n relativeSeries: ICartesianSeries\n useElementStackEnd?: boolean\n}) => {\n const { anchor, seriesData, relativeSeries, useElementStackEnd = false } = options\n\n if (!anchor.stackGroupDatum) {\n const runtimeMatches = anchor.matchedDatum\n ? seriesData.filter((datum) => isSubset(anchor.matchedDatum as Datum, datum))\n : []\n\n if (!useElementStackEnd) {\n return runtimeMatches[0] ?? anchor.coordinateDatum\n }\n\n const runtimeMatch = runtimeMatches[0]\n const runtimeStackEnd = Number(runtimeMatch?.[STACK_END_FIELD])\n\n return {\n ...(runtimeMatch ?? anchor.coordinateDatum),\n [relativeSeries.getStackValueField()]: Number.isFinite(runtimeStackEnd) ? runtimeStackEnd : anchor.value,\n }\n }\n\n const runtimeMatches = seriesData.filter((datum) => isSubset(anchor.stackGroupDatum as Datum, datum))\n const runtimeStackTotal = getStackRuntimeTotal(runtimeMatches)\n\n return {\n ...(runtimeMatches[0] ?? anchor.coordinateDatum),\n [relativeSeries.getStackValueField()]: runtimeStackTotal ?? anchor.value,\n }\n}\n\nexport const getRuntimeDifferenceValue = (options: {\n anchor: ResolvedDifferenceAnchor\n seriesData: Datum[]\n useElementStackEnd?: boolean\n}) => {\n const { anchor, seriesData, useElementStackEnd = false } = options\n\n if (anchor.stackGroupDatum) {\n const runtimeMatches = seriesData.filter((datum) => isSubset(anchor.stackGroupDatum as Datum, datum))\n return getStackRuntimeTotal(runtimeMatches) ?? anchor.value\n }\n\n if (!useElementStackEnd || !anchor.matchedDatum) {\n return anchor.value\n }\n\n const runtimeMatch = seriesData.find((datum) => isSubset(anchor.matchedDatum as Datum, datum))\n const runtimeStackEnd = Number(runtimeMatch?.[STACK_END_FIELD])\n\n return Number.isFinite(runtimeStackEnd) ? runtimeStackEnd : anchor.value\n}\n\nexport const getDifferenceValue = (\n startValue: number,\n endValue: number,\n differenceType: 'absolute' | 'percent' = 'absolute',\n) => {\n if (differenceType === 'percent') {\n if (startValue === 0) {\n throw new Error('annotationDifferenceLine percent difference cannot be computed because start value is 0')\n }\n\n return (endValue - startValue) / startValue\n }\n\n return endValue - startValue\n}\n\nexport const buildDifferenceText = (\n startValue: number,\n endValue: number,\n differenceType: 'absolute' | 'percent' = 'absolute',\n formatter?: (value: number) => string,\n) => {\n const differenceValue = getDifferenceValue(startValue, endValue, differenceType)\n\n if (formatter) {\n return formatter(differenceValue)\n }\n\n if (differenceType === 'percent') {\n return `${(differenceValue * 100).toFixed(2)}%`\n }\n\n return `${differenceValue}`\n}\n\nexport const inferDifferenceConnectDirection = (vseed: VSeed, values: [number, number]) => {\n const isNegativeSide = values.every((value) => value < 0)\n\n if (isBarLikeChart(vseed)) {\n return isNegativeSide ? 'left' : 'right'\n }\n\n return isNegativeSide ? 'bottom' : 'top'\n}\n\nexport const inferDifferenceBracketDirection = (\n start: ResolvedDifferenceAnchor,\n end: ResolvedDifferenceAnchor,\n): 'left' | 'right' => {\n if (start.bandIndex === undefined || end.bandIndex === undefined) {\n return 'right'\n }\n\n return start.bandIndex <= end.bandIndex ? 'right' : 'left'\n}\n"],"names":["STACK_END_FIELD","toArray","value","Array","getDifferenceBandFields","spec","getDifferenceValueField","valueField","Error","normalizeDifferenceValue","selectorLabel","field","numberValue","Number","buildStackGroupDatum","datum","bandFields","Object","resolveBandIndex","dataset","bandDatum","bandIndex","isSubset","undefined","buildFallbackSelectorDatum","selectorValue","selectorList","fallbackDatum","currentSelector","isValueSelector","isFieldSelector","isMeasureSelector","operator","selectorValues","isDimensionSelector","isPartialDatumSelector","inferFallbackValue","numericCandidateKeys","key","resolveFallbackAnchor","options","inferredValue","coordinateDatum","hasMixedSigns","values","nonZeroValues","getDifferenceLineStackResolveMode","vseed","advancedVSeed","hasMultipleMeasure","hasMultipleMeasureInSingleView","usesDifferenceLineElementStackEnd","resolveDifferenceAnchor","stackResolveMode","allowSelectorFallback","matches","selector","stackGroups","Map","stackGroupDatum","JSON","groupRows","groupValues","sum","getStackRuntimeTotal","runtimeMatches","stackEndValues","Math","buildDifferenceCoordinateDatum","anchor","seriesData","relativeSeries","useElementStackEnd","runtimeMatch","runtimeStackEnd","runtimeStackTotal","getRuntimeDifferenceValue","getDifferenceValue","startValue","endValue","differenceType","buildDifferenceText","formatter","differenceValue","inferDifferenceConnectDirection","isNegativeSide","isBarLikeChart","inferDifferenceBracketDirection","start","end"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ export declare const generateAnnotationPointPipe: (options: {
|
|
|
4
4
|
findSelectedDatas?: (options: {
|
|
5
5
|
dataset: Datum[];
|
|
6
6
|
selector: Selector | Selectors | undefined | null;
|
|
7
|
+
measureId?: string | null;
|
|
7
8
|
dynamicFilter?: ChartDynamicFilter;
|
|
8
9
|
spec: ISpec;
|
|
9
10
|
context: SpecPipelineContext;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { selector, selectorWithDynamicFilter } from "../../../../../dataSelector/index.js";
|
|
2
|
+
import { MeasureId } from "../../../../../dataReshape/constant.js";
|
|
2
3
|
import { isSubset } from "./utils.js";
|
|
3
4
|
import { ANNOTATION_Z_INDEX } from "../../../../utils/constant.js";
|
|
4
5
|
import { isBarLikeChart } from "../../../../utils/chatType.js";
|
|
5
6
|
const generateAnnotationPointPipe = (options)=>{
|
|
6
7
|
const findSelectedDatas = options.findSelectedDatas ?? ((opts)=>{
|
|
7
|
-
const { dataset, selector: s, dynamicFilter } = opts;
|
|
8
|
-
return dataset.filter((datum)=>
|
|
8
|
+
const { dataset, selector: s, measureId, dynamicFilter } = opts;
|
|
9
|
+
return dataset.filter((datum)=>{
|
|
10
|
+
const isSelected = dynamicFilter ? selectorWithDynamicFilter(datum, dynamicFilter, s) : selector(datum, s);
|
|
11
|
+
return isSelected && (!measureId || datum[MeasureId] === measureId);
|
|
12
|
+
});
|
|
9
13
|
});
|
|
10
14
|
const generateMarkPoint = options.generateMarkPoint ?? ((datum)=>[
|
|
11
15
|
{
|
|
@@ -43,11 +47,12 @@ const generateAnnotationPointPipe = (options)=>{
|
|
|
43
47
|
textBaseline: 'top'
|
|
44
48
|
};
|
|
45
49
|
const markPoint = annotationPointList.flatMap((annotationPoint)=>{
|
|
46
|
-
const { selector: selectorPoint, dynamicFilter, text = '', textColor = theme?.textColor ?? '#ffffff', textFontSize = theme?.textFontSize ?? 12, textFontWeight = theme?.textFontWeight ?? 400, textAlign = defaultStyle.textAlign, textBaseline = defaultStyle.textBaseline, textBackgroundBorderColor = theme?.textBackgroundBorderColor, textBackgroundBorderRadius = theme?.textBackgroundBorderRadius ?? 4, textBackgroundBorderWidth = theme?.textBackgroundBorderWidth ?? 1, textBackgroundColor = theme?.textBackgroundColor ?? '#212121', textBackgroundPadding = theme?.textBackgroundPadding ?? 2, textBackgroundVisible = theme?.textBackgroundVisible ?? true, offsetX = theme?.offsetX ?? 0, offsetY = theme?.offsetY ?? 0 } = annotationPoint;
|
|
50
|
+
const { selector: selectorPoint, measureId, dynamicFilter, text = '', textColor = theme?.textColor ?? '#ffffff', textFontSize = theme?.textFontSize ?? 12, textFontWeight = theme?.textFontWeight ?? 400, textAlign = defaultStyle.textAlign, textBaseline = defaultStyle.textBaseline, textBackgroundBorderColor = theme?.textBackgroundBorderColor, textBackgroundBorderRadius = theme?.textBackgroundBorderRadius ?? 4, textBackgroundBorderWidth = theme?.textBackgroundBorderWidth ?? 1, textBackgroundColor = theme?.textBackgroundColor ?? '#212121', textBackgroundPadding = theme?.textBackgroundPadding ?? 2, textBackgroundVisible = theme?.textBackgroundVisible ?? true, offsetX = theme?.offsetX ?? 0, offsetY = theme?.offsetY ?? 0 } = annotationPoint;
|
|
47
51
|
const dataset = advancedVSeed.dataset.flat();
|
|
48
52
|
const selectedData = selectorPoint || dynamicFilter ? findSelectedDatas({
|
|
49
53
|
dataset,
|
|
50
54
|
selector: selectorPoint,
|
|
55
|
+
measureId,
|
|
51
56
|
dynamicFilter,
|
|
52
57
|
spec,
|
|
53
58
|
context
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/chart/pipes/annotation/annotationPointCommon.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/annotation/annotationPointCommon.ts"],"sourcesContent":["import type { ISpec, IMarkPointSpec } from '@visactor/vchart'\nimport { selector, selectorWithDynamicFilter } from '../../../../../dataSelector'\nimport type {\n ChartDynamicFilter,\n Datum,\n Selector,\n Selectors,\n SpecPipelineContext,\n VChartSpecPipe,\n VSeed,\n} from 'src/types'\nimport { isSubset } from './utils'\nimport { ANNOTATION_Z_INDEX } from '../../../../utils/constant'\nimport { isBarLikeChart } from 'src/pipeline/utils/chatType'\nexport const generateAnnotationPointPipe = (options: {\n findSelectedDatas?: (options: {\n dataset: Datum[]\n selector: Selector | Selectors | undefined | null\n dynamicFilter?: ChartDynamicFilter\n spec: ISpec\n context: SpecPipelineContext\n }) => Datum[]\n generateMarkPoint?: (datum: Datum, spec: ISpec, context: SpecPipelineContext) => IMarkPointSpec[] | undefined\n}) => {\n const findSelectedDatas =\n options.findSelectedDatas ??\n ((opts) => {\n const { dataset, selector: s, dynamicFilter } = opts\n return dataset.filter((datum) => {\n
|
|
1
|
+
{"version":3,"file":"pipeline/spec/chart/pipes/annotation/annotationPointCommon.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/annotation/annotationPointCommon.ts"],"sourcesContent":["import type { ISpec, IMarkPointSpec } from '@visactor/vchart'\nimport { selector, selectorWithDynamicFilter } from '../../../../../dataSelector'\nimport { MeasureId } from 'src/dataReshape/constant'\nimport type {\n ChartDynamicFilter,\n Datum,\n Selector,\n Selectors,\n SpecPipelineContext,\n VChartSpecPipe,\n VSeed,\n} from 'src/types'\nimport { isSubset } from './utils'\nimport { ANNOTATION_Z_INDEX } from '../../../../utils/constant'\nimport { isBarLikeChart } from 'src/pipeline/utils/chatType'\nexport const generateAnnotationPointPipe = (options: {\n findSelectedDatas?: (options: {\n dataset: Datum[]\n selector: Selector | Selectors | undefined | null\n measureId?: string | null\n dynamicFilter?: ChartDynamicFilter\n spec: ISpec\n context: SpecPipelineContext\n }) => Datum[]\n generateMarkPoint?: (datum: Datum, spec: ISpec, context: SpecPipelineContext) => IMarkPointSpec[] | undefined\n}) => {\n const findSelectedDatas =\n options.findSelectedDatas ??\n ((opts) => {\n const { dataset, selector: s, measureId, dynamicFilter } = opts\n return dataset.filter((datum) => {\n const isSelected = dynamicFilter ? selectorWithDynamicFilter(datum, dynamicFilter, s) : selector(datum, s)\n return isSelected && (!measureId || datum[MeasureId] === measureId)\n })\n })\n const generateMarkPoint =\n options.generateMarkPoint ??\n ((datum: Datum) => {\n return [\n {\n coordinate: (data: Datum[], context) => {\n const targetDatum = data.find((item) => isSubset(datum, item))\n if (context.getStack() === true) {\n const stackedDatum = { ...datum, ...targetDatum }\n return {\n ...stackedDatum,\n [context.getStackValueField()]: stackedDatum['__VCHART_STACK_END'],\n }\n }\n\n return targetDatum\n },\n },\n ]\n })\n\n return ((spec: ISpec, context: SpecPipelineContext) => {\n const { advancedVSeed, vseed } = context\n const { annotation, config } = advancedVSeed\n\n if (!annotation || !annotation.annotationPoint) {\n return spec\n }\n\n const theme = config?.[vseed.chartType as 'column']?.annotation?.annotationPoint\n const { annotationPoint } = annotation\n const annotationPointList = Array.isArray(annotationPoint) ? annotationPoint : [annotationPoint]\n const isHorizontalBar = isBarLikeChart(advancedVSeed as VSeed)\n const defaultStyle = isHorizontalBar\n ? {\n textAlign: 'right',\n textBaseline: 'middle',\n }\n : {\n textAlign: 'center',\n textBaseline: 'top',\n }\n\n const markPoint = annotationPointList.flatMap((annotationPoint) => {\n const {\n selector: selectorPoint,\n measureId,\n dynamicFilter,\n text = '',\n textColor = theme?.textColor ?? '#ffffff',\n textFontSize = theme?.textFontSize ?? 12,\n textFontWeight = theme?.textFontWeight ?? 400,\n textAlign = defaultStyle.textAlign,\n textBaseline = defaultStyle.textBaseline,\n textBackgroundBorderColor = theme?.textBackgroundBorderColor,\n textBackgroundBorderRadius = theme?.textBackgroundBorderRadius ?? 4,\n textBackgroundBorderWidth = theme?.textBackgroundBorderWidth ?? 1,\n textBackgroundColor = theme?.textBackgroundColor ?? '#212121',\n textBackgroundPadding = theme?.textBackgroundPadding ?? 2,\n textBackgroundVisible = theme?.textBackgroundVisible ?? true,\n offsetX = theme?.offsetX ?? 0,\n offsetY = theme?.offsetY ?? 0,\n } = annotationPoint\n\n const dataset = advancedVSeed.dataset.flat()\n const selectedData =\n selectorPoint || dynamicFilter\n ? findSelectedDatas({\n dataset,\n selector: selectorPoint,\n measureId,\n dynamicFilter,\n spec,\n context,\n })\n : []\n const dx = -10 - (isHorizontalBar ? (textFontSize as number) : 0) // 由于vchart tag实现问题,需要设置这个强制偏移量\n const dy = isHorizontalBar ? 0 : (textFontSize as number)\n const markPointStyle = {\n zIndex: ANNOTATION_Z_INDEX,\n regionRelative: true,\n itemLine: {\n visible: false,\n },\n itemContent: {\n offsetY,\n offsetX,\n confine: true,\n text: {\n text: text,\n labelBackground: {\n visible: textBackgroundVisible,\n padding: textBackgroundPadding,\n style: {\n opacity: 0.95,\n cornerRadius: textBackgroundBorderRadius ?? 4,\n fill: textBackgroundColor,\n stroke: textBackgroundBorderColor,\n lineWidth: textBackgroundBorderWidth,\n dx,\n dy,\n },\n },\n },\n style: {\n opacity: 0.95,\n visible: true,\n textAlign: textAlign,\n textBaseline: textBaseline,\n fill: textColor,\n stroke: textBackgroundColor,\n lineWidth: 1,\n fontSize: textFontSize,\n fontWeight: textFontWeight,\n dx,\n dy,\n },\n },\n } as Partial<IMarkPointSpec>\n\n return selectedData.reduce((res: IMarkPointSpec[], datum) => {\n const marks = generateMarkPoint(datum, spec, context)\n\n if (marks && marks.length) {\n marks.forEach((mark) => {\n res.push({\n ...markPointStyle,\n ...mark,\n } as IMarkPointSpec)\n })\n }\n\n return res\n }, [])\n }) as unknown as IMarkPointSpec[]\n\n return {\n ...spec,\n markPoint,\n } as ISpec\n }) as VChartSpecPipe\n}\n"],"names":["generateAnnotationPointPipe","options","findSelectedDatas","opts","dataset","s","measureId","dynamicFilter","datum","isSelected","selectorWithDynamicFilter","selector","MeasureId","generateMarkPoint","data","context","targetDatum","item","isSubset","stackedDatum","spec","advancedVSeed","vseed","annotation","config","theme","annotationPoint","annotationPointList","Array","isHorizontalBar","isBarLikeChart","defaultStyle","markPoint","selectorPoint","text","textColor","textFontSize","textFontWeight","textAlign","textBaseline","textBackgroundBorderColor","textBackgroundBorderRadius","textBackgroundBorderWidth","textBackgroundColor","textBackgroundPadding","textBackgroundVisible","offsetX","offsetY","selectedData","dx","dy","markPointStyle","ANNOTATION_Z_INDEX","res","marks","mark"],"mappings":"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"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { selector, selectorWithDynamicFilter } from "../../../../../dataSelector/index.js";
|
|
2
|
+
import { MeasureId } from "../../../../../dataReshape/constant.js";
|
|
2
3
|
import { isSubset } from "./utils.js";
|
|
3
4
|
import { flatReshapeMeasures } from "../../../../utils/index.js";
|
|
4
|
-
import { MeasureId } from "../../../../../dataReshape/constant.js";
|
|
5
5
|
import { pickWithout } from "@visactor/vutils";
|
|
6
6
|
import { generateAnnotationPointPipe } from "./annotationPointCommon.js";
|
|
7
7
|
const annotationPointOfDualAxis = generateAnnotationPointPipe({
|
|
8
8
|
findSelectedDatas: (options)=>{
|
|
9
|
-
const { dataset, selector: s, dynamicFilter, context } = options;
|
|
9
|
+
const { dataset, selector: s, measureId, dynamicFilter, context } = options;
|
|
10
10
|
return dataset.reduce((res, d)=>{
|
|
11
11
|
const { advancedVSeed } = context;
|
|
12
12
|
const allMeasureIds = flatReshapeMeasures(advancedVSeed.reshapeMeasures ?? []).map((m)=>m.id);
|
|
13
13
|
const pickedDatum = pickWithout(d, allMeasureIds.filter((id)=>id !== d[MeasureId]));
|
|
14
14
|
const shouldSelect = dynamicFilter ? selectorWithDynamicFilter(pickedDatum, dynamicFilter, s) : selector(pickedDatum, s);
|
|
15
|
-
if (shouldSelect) res.push(pickedDatum);
|
|
15
|
+
if (shouldSelect && (!measureId || pickedDatum[MeasureId] === measureId)) res.push(pickedDatum);
|
|
16
16
|
return res;
|
|
17
17
|
}, []);
|
|
18
18
|
},
|