@visactor/vseed 0.5.0 → 0.5.2
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/builder/builder/advanced/colorItems.d.ts +1 -0
- package/dist/esm/builder/builder/advanced/colorItems.js +21 -1
- package/dist/esm/builder/builder/advanced/colorItems.js.map +1 -1
- package/dist/esm/builder/builder/buildSpec.js.map +1 -1
- package/dist/esm/builder/builder/builder.d.ts +4 -0
- package/dist/esm/builder/builder/builder.js +2 -1
- package/dist/esm/builder/builder/builder.js.map +1 -1
- package/dist/esm/dataSelector/selector.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/animation/bar.js +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/animation/bar.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/animation/lineOrArea.d.ts +4 -0
- package/dist/esm/pipeline/spec/chart/pipes/animation/radar.d.ts +4 -0
- package/dist/esm/pipeline/spec/chart/pipes/animation/utils/index.d.ts +1 -60
- package/dist/esm/pipeline/spec/chart/pipes/animation/utils/index.js +2 -44
- package/dist/esm/pipeline/spec/chart/pipes/animation/utils/index.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/animation/utils/pointAtmosphere.d.ts +65 -0
- package/dist/esm/pipeline/spec/chart/pipes/animation/utils/pointAtmosphere.js +56 -0
- package/dist/esm/pipeline/spec/chart/pipes/animation/utils/pointAtmosphere.js.map +1 -0
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationArea.js +2 -2
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationArea.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationAreaBand.js +2 -2
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationAreaBand.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.js +63 -18
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationDifferenceLine.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationHorizontalLine.js +7 -13
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationHorizontalLine.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointCommon.js +2 -2
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationPointCommon.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationVerticalLine.js +9 -15
- package/dist/esm/pipeline/spec/chart/pipes/annotation/annotationVerticalLine.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/utils.d.ts +2 -0
- package/dist/esm/pipeline/spec/chart/pipes/annotation/utils.js +15 -1
- package/dist/esm/pipeline/spec/chart/pipes/annotation/utils.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/stack/stackCornerRadius.js +18 -39
- package/dist/esm/pipeline/spec/chart/pipes/stack/stackCornerRadius.js.map +1 -1
- package/dist/esm/pipeline/spec/chart/pipes/stack/stackCornerRadiusUtils.d.ts +4 -0
- package/dist/esm/pipeline/spec/chart/pipes/stack/stackCornerRadiusUtils.js +50 -0
- package/dist/esm/pipeline/spec/chart/pipes/stack/stackCornerRadiusUtils.js.map +1 -0
- package/dist/esm/pipeline/utils/sandbox/execute.js.map +1 -1
- package/dist/esm/theme/tokenTheme.d.ts +6 -0
- package/dist/esm/theme/tokenTheme.js +36 -7
- package/dist/esm/theme/tokenTheme.js.map +1 -1
- package/dist/esm/types/builder/builder.d.ts +1 -0
- package/dist/esm/types/builder/builder.js.map +1 -1
- package/dist/esm/types/chartType/area/zArea.d.ts +10 -0
- package/dist/esm/types/chartType/bar/zBar.d.ts +10 -0
- package/dist/esm/types/chartType/barParallel/zBarParallel.d.ts +10 -0
- package/dist/esm/types/chartType/column/zColumn.d.ts +10 -0
- package/dist/esm/types/chartType/columnParallel/zColumnParallel.d.ts +10 -0
- package/dist/esm/types/chartType/line/zLine.d.ts +10 -0
- package/dist/esm/types/properties/annotation/annotation.d.ts +10 -0
- package/dist/esm/types/properties/annotation/annotationDifferenceLine.d.ts +4 -0
- package/dist/esm/types/properties/annotation/zAnnotationDifferenceLine.d.ts +5 -0
- package/dist/esm/types/properties/annotation/zAnnotationDifferenceLine.js +6 -1
- package/dist/esm/types/properties/annotation/zAnnotationDifferenceLine.js.map +1 -1
- package/dist/esm/types/properties/config/annotation/annotation.d.ts +32 -5
- package/dist/esm/types/properties/config/annotation/zAnnotation.d.ts +30 -4
- package/dist/esm/types/properties/config/annotation/zAnnotation.js +11 -1
- package/dist/esm/types/properties/config/annotation/zAnnotation.js.map +1 -1
- package/dist/esm/types/properties/config/area.d.ts +30 -4
- package/dist/esm/types/properties/config/bar.d.ts +45 -6
- package/dist/esm/types/properties/config/boxplot.d.ts +15 -2
- package/dist/esm/types/properties/config/column.d.ts +45 -6
- package/dist/esm/types/properties/config/config.d.ts +285 -38
- package/dist/esm/types/properties/config/dualAxis.d.ts +15 -2
- package/dist/esm/types/properties/config/histogram.d.ts +15 -2
- package/dist/esm/types/properties/config/line.d.ts +15 -2
- package/dist/esm/types/properties/config/race.d.ts +90 -12
- package/dist/esm/types/properties/config/scatter.d.ts +15 -2
- package/dist/esm/types/properties/theme/customTheme.d.ts +570 -76
- package/dist/umd/index.js +332 -184
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -8
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { unique } from "remeda";
|
|
2
2
|
import { isPivotTable, isTable } from "../../../pipeline/index.js";
|
|
3
|
+
import { isLinearColor } from "../../../pipeline/spec/chart/pipes/index.js";
|
|
4
|
+
import { createSpecifiedForColorMapping } from "../../../pipeline/spec/chart/pipes/color/color.js";
|
|
3
5
|
const getColorItems = (builder)=>{
|
|
4
6
|
const advancedVSeed = builder.advancedVSeed;
|
|
5
7
|
if (!advancedVSeed || isTable(builder.vseed) || isPivotTable(builder.vseed)) return [];
|
|
@@ -24,6 +26,24 @@ const getColorIdMap = (builder)=>{
|
|
|
24
26
|
}), {});
|
|
25
27
|
return colorIdMap;
|
|
26
28
|
};
|
|
27
|
-
|
|
29
|
+
const getColorValueMap = (builder)=>{
|
|
30
|
+
const advancedVSeed = builder.advancedVSeed;
|
|
31
|
+
if (!advancedVSeed || isTable(builder.vseed) || isPivotTable(builder.vseed) || isLinearColor(advancedVSeed, builder.vseed)) return;
|
|
32
|
+
const { datasetReshapeInfo, chartType } = advancedVSeed;
|
|
33
|
+
const unfoldInfo = datasetReshapeInfo[0]?.unfoldInfo;
|
|
34
|
+
const baseConfig = advancedVSeed.config?.[chartType];
|
|
35
|
+
const colorConfig = baseConfig?.color;
|
|
36
|
+
if (!unfoldInfo || !colorConfig) return;
|
|
37
|
+
const colorItems = unfoldInfo.colorItems ?? [];
|
|
38
|
+
const colorIdMap = unfoldInfo.colorIdMap;
|
|
39
|
+
const colorScheme = colorConfig.colorScheme ?? [];
|
|
40
|
+
const specified = createSpecifiedForColorMapping(colorConfig.colorMapping, colorIdMap, colorItems) ?? {};
|
|
41
|
+
return colorItems.reduce((prev, colorId, index)=>{
|
|
42
|
+
const colorValue = specified[colorId] ?? colorScheme[index % colorScheme.length];
|
|
43
|
+
if (colorValue) prev[colorId] = colorValue;
|
|
44
|
+
return prev;
|
|
45
|
+
}, {});
|
|
46
|
+
};
|
|
47
|
+
export { getColorIdMap, getColorItems, getColorValueMap };
|
|
28
48
|
|
|
29
49
|
//# sourceMappingURL=colorItems.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder/builder/advanced/colorItems.js","sources":["../../../../../src/builder/builder/advanced/colorItems.ts"],"sourcesContent":["import { unique } from 'remeda'\nimport type { Builder } from '../builder'\nimport { isPivotTable, isTable } from 'src/pipeline'\n\nexport const getColorItems = (builder: Builder): { id: string; alias: string }[] => {\n const advancedVSeed = builder.advancedVSeed\n\n if (!advancedVSeed || isTable(builder.vseed) || isPivotTable(builder.vseed)) {\n return []\n }\n\n const { datasetReshapeInfo } = advancedVSeed\n const colorItems = unique(datasetReshapeInfo.flatMap((d) => d.unfoldInfo.colorItems))\n const colorIdMap = datasetReshapeInfo.reduce<Record<string, { id: string; alias: string }>>((prev, cur) => {\n return { ...prev, ...cur.unfoldInfo.colorIdMap }\n }, {})\n\n return colorItems.map((d) => ({\n id: d,\n alias: colorIdMap[d]?.alias,\n }))\n}\n\nexport const getColorIdMap = (builder: Builder): Record<string, { id: string; alias: string }> => {\n const advancedVSeed = builder.advancedVSeed\n\n if (!advancedVSeed || isTable(builder.vseed) || isPivotTable(builder.vseed)) {\n return {}\n }\n\n const { datasetReshapeInfo } = advancedVSeed\n const colorIdMap = datasetReshapeInfo.reduce<Record<string, { id: string; alias: string }>>((prev, cur) => {\n return { ...prev, ...cur.unfoldInfo.colorIdMap }\n }, {})\n\n return colorIdMap\n}\n"],"names":["getColorItems","builder","advancedVSeed","isTable","isPivotTable","datasetReshapeInfo","colorItems","unique","d","colorIdMap","prev","cur","getColorIdMap"],"mappings":"
|
|
1
|
+
{"version":3,"file":"builder/builder/advanced/colorItems.js","sources":["../../../../../src/builder/builder/advanced/colorItems.ts"],"sourcesContent":["import { unique } from 'remeda'\nimport type { Builder } from '../builder'\nimport { isPivotTable, isTable } from 'src/pipeline'\nimport { isLinearColor } from 'src/pipeline/spec/chart/pipes'\nimport { createSpecifiedForColorMapping } from 'src/pipeline/spec/chart/pipes/color/color'\nimport type { Color } from 'src/types'\n\nexport const getColorItems = (builder: Builder): { id: string; alias: string }[] => {\n const advancedVSeed = builder.advancedVSeed\n\n if (!advancedVSeed || isTable(builder.vseed) || isPivotTable(builder.vseed)) {\n return []\n }\n\n const { datasetReshapeInfo } = advancedVSeed\n const colorItems = unique(datasetReshapeInfo.flatMap((d) => d.unfoldInfo.colorItems))\n const colorIdMap = datasetReshapeInfo.reduce<Record<string, { id: string; alias: string }>>((prev, cur) => {\n return { ...prev, ...cur.unfoldInfo.colorIdMap }\n }, {})\n\n return colorItems.map((d) => ({\n id: d,\n alias: colorIdMap[d]?.alias,\n }))\n}\n\nexport const getColorIdMap = (builder: Builder): Record<string, { id: string; alias: string }> => {\n const advancedVSeed = builder.advancedVSeed\n\n if (!advancedVSeed || isTable(builder.vseed) || isPivotTable(builder.vseed)) {\n return {}\n }\n\n const { datasetReshapeInfo } = advancedVSeed\n const colorIdMap = datasetReshapeInfo.reduce<Record<string, { id: string; alias: string }>>((prev, cur) => {\n return { ...prev, ...cur.unfoldInfo.colorIdMap }\n }, {})\n\n return colorIdMap\n}\n\nexport const getColorValueMap = (builder: Builder): Record<string, string> | undefined => {\n const advancedVSeed = builder.advancedVSeed\n\n if (\n !advancedVSeed ||\n isTable(builder.vseed) ||\n isPivotTable(builder.vseed) ||\n isLinearColor(advancedVSeed, builder.vseed)\n ) {\n return undefined\n }\n\n const { datasetReshapeInfo, chartType } = advancedVSeed\n const unfoldInfo = datasetReshapeInfo[0]?.unfoldInfo\n const baseConfig = advancedVSeed.config?.[chartType] as { color?: Color } | undefined\n const colorConfig = baseConfig?.color\n\n if (!unfoldInfo || !colorConfig) {\n return undefined\n }\n\n const colorItems = unfoldInfo.colorItems ?? []\n const colorIdMap = unfoldInfo.colorIdMap\n const colorScheme = colorConfig.colorScheme ?? []\n const specified = createSpecifiedForColorMapping(colorConfig.colorMapping, colorIdMap, colorItems) ?? {}\n\n return colorItems.reduce<Record<string, string>>((prev, colorId, index) => {\n const colorValue = specified[colorId] ?? colorScheme[index % colorScheme.length]\n\n if (colorValue) {\n prev[colorId] = colorValue\n }\n\n return prev\n }, {})\n}\n"],"names":["getColorItems","builder","advancedVSeed","isTable","isPivotTable","datasetReshapeInfo","colorItems","unique","d","colorIdMap","prev","cur","getColorIdMap","getColorValueMap","isLinearColor","chartType","unfoldInfo","baseConfig","colorConfig","colorScheme","specified","createSpecifiedForColorMapping","colorId","index","colorValue"],"mappings":";;;;AAOO,MAAMA,gBAAgB,CAACC;IAC5B,MAAMC,gBAAgBD,QAAQ,aAAa;IAE3C,IAAI,CAACC,iBAAiBC,QAAQF,QAAQ,KAAK,KAAKG,aAAaH,QAAQ,KAAK,GACxE,OAAO,EAAE;IAGX,MAAM,EAAEI,kBAAkB,EAAE,GAAGH;IAC/B,MAAMI,aAAaC,OAAOF,mBAAmB,OAAO,CAAC,CAACG,IAAMA,EAAE,UAAU,CAAC,UAAU;IACnF,MAAMC,aAAaJ,mBAAmB,MAAM,CAAgD,CAACK,MAAMC,MAC1F;YAAE,GAAGD,IAAI;YAAE,GAAGC,IAAI,UAAU,CAAC,UAAU;QAAC,IAC9C,CAAC;IAEJ,OAAOL,WAAW,GAAG,CAAC,CAACE,IAAO;YAC5B,IAAIA;YACJ,OAAOC,UAAU,CAACD,EAAE,EAAE;QACxB;AACF;AAEO,MAAMI,gBAAgB,CAACX;IAC5B,MAAMC,gBAAgBD,QAAQ,aAAa;IAE3C,IAAI,CAACC,iBAAiBC,QAAQF,QAAQ,KAAK,KAAKG,aAAaH,QAAQ,KAAK,GACxE,OAAO,CAAC;IAGV,MAAM,EAAEI,kBAAkB,EAAE,GAAGH;IAC/B,MAAMO,aAAaJ,mBAAmB,MAAM,CAAgD,CAACK,MAAMC,MAC1F;YAAE,GAAGD,IAAI;YAAE,GAAGC,IAAI,UAAU,CAAC,UAAU;QAAC,IAC9C,CAAC;IAEJ,OAAOF;AACT;AAEO,MAAMI,mBAAmB,CAACZ;IAC/B,MAAMC,gBAAgBD,QAAQ,aAAa;IAE3C,IACE,CAACC,iBACDC,QAAQF,QAAQ,KAAK,KACrBG,aAAaH,QAAQ,KAAK,KAC1Ba,cAAcZ,eAAeD,QAAQ,KAAK,GAE1C;IAGF,MAAM,EAAEI,kBAAkB,EAAEU,SAAS,EAAE,GAAGb;IAC1C,MAAMc,aAAaX,kBAAkB,CAAC,EAAE,EAAE;IAC1C,MAAMY,aAAaf,cAAc,MAAM,EAAE,CAACa,UAAU;IACpD,MAAMG,cAAcD,YAAY;IAEhC,IAAI,CAACD,cAAc,CAACE,aAClB;IAGF,MAAMZ,aAAaU,WAAW,UAAU,IAAI,EAAE;IAC9C,MAAMP,aAAaO,WAAW,UAAU;IACxC,MAAMG,cAAcD,YAAY,WAAW,IAAI,EAAE;IACjD,MAAME,YAAYC,+BAA+BH,YAAY,YAAY,EAAET,YAAYH,eAAe,CAAC;IAEvG,OAAOA,WAAW,MAAM,CAAyB,CAACI,MAAMY,SAASC;QAC/D,MAAMC,aAAaJ,SAAS,CAACE,QAAQ,IAAIH,WAAW,CAACI,QAAQJ,YAAY,MAAM,CAAC;QAEhF,IAAIK,YACFd,IAAI,CAACY,QAAQ,GAAGE;QAGlB,OAAOd;IACT,GAAG,CAAC;AACN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder/builder/buildSpec.js","sources":["../../../../src/builder/builder/buildSpec.ts"],"sourcesContent":["import type { AdvancedVSeed, Pipe, Spec, SpecPipelineContext } from 'src/types'\nimport { Builder } from './builder'\nimport { execPipeline } from '../../pipeline'\nimport { intl } from 'src/i18n'\n\nexport const buildSpec = (builder: Builder, advancedVSeed: AdvancedVSeed): Spec => {\n const start = typeof performance !== 'undefined' ? performance.now() : Date.now()\n\n const { chartType } = builder.vseed\n\n const pipeline = Builder.getSpecPipeline(chartType)\n if (!pipeline) {\n throw new Error(\n `please invoke registerAll or register ${chartType} before build, no spec pipeline for chartType ${chartType}`,\n )\n }\n\n const context: SpecPipelineContext = {\n vseed: builder.vseed,\n advancedVSeed,\n }\n if (builder.locale) {\n intl.setLocale(builder.locale)\n }\n\n try {\n const spec = execPipeline<Spec, SpecPipelineContext>(pipeline as Array<Pipe<Spec, SpecPipelineContext>>, context)\n builder.spec = spec as Spec\n return spec as Spec\n } catch (e) {\n //
|
|
1
|
+
{"version":3,"file":"builder/builder/buildSpec.js","sources":["../../../../src/builder/builder/buildSpec.ts"],"sourcesContent":["import type { AdvancedVSeed, Pipe, Spec, SpecPipelineContext } from 'src/types'\nimport { Builder } from './builder'\nimport { execPipeline } from '../../pipeline'\nimport { intl } from 'src/i18n'\n\nexport const buildSpec = (builder: Builder, advancedVSeed: AdvancedVSeed): Spec => {\n const start = typeof performance !== 'undefined' ? performance.now() : Date.now()\n\n const { chartType } = builder.vseed\n\n const pipeline = Builder.getSpecPipeline(chartType)\n if (!pipeline) {\n throw new Error(\n `please invoke registerAll or register ${chartType} before build, no spec pipeline for chartType ${chartType}`,\n )\n }\n\n const context: SpecPipelineContext = {\n vseed: builder.vseed,\n advancedVSeed,\n }\n if (builder.locale) {\n intl.setLocale(builder.locale)\n }\n\n try {\n const spec = execPipeline<Spec, SpecPipelineContext>(pipeline as Array<Pipe<Spec, SpecPipelineContext>>, context)\n builder.spec = spec as Spec\n return spec as Spec\n } catch (e) {\n // oxlint-disable-next-line no-console\n console.error(e)\n throw new Error(`buildSpec error: ${(e as Error).message}`)\n } finally {\n const end = typeof performance !== 'undefined' ? performance.now() : Date.now()\n builder.performance['buildSpec'] = `${(end - start).toFixed(4)}ms`\n }\n}\n"],"names":["buildSpec","builder","advancedVSeed","start","performance","Date","chartType","pipeline","Builder","Error","context","intl","spec","execPipeline","e","console","end"],"mappings":";;;AAKO,MAAMA,YAAY,CAACC,SAAkBC;IAC1C,MAAMC,QAAQ,AAAuB,MAAvB,OAAOC,cAA8BA,YAAY,GAAG,KAAKC,KAAK,GAAG;IAE/E,MAAM,EAAEC,SAAS,EAAE,GAAGL,QAAQ,KAAK;IAEnC,MAAMM,WAAWC,QAAQ,eAAe,CAACF;IACzC,IAAI,CAACC,UACH,MAAM,IAAIE,MACR,CAAC,sCAAsC,EAAEH,UAAU,8CAA8C,EAAEA,WAAW;IAIlH,MAAMI,UAA+B;QACnC,OAAOT,QAAQ,KAAK;QACpBC;IACF;IACA,IAAID,QAAQ,MAAM,EAChBU,KAAK,SAAS,CAACV,QAAQ,MAAM;IAG/B,IAAI;QACF,MAAMW,OAAOC,aAAwCN,UAAoDG;QACzGT,QAAQ,IAAI,GAAGW;QACf,OAAOA;IACT,EAAE,OAAOE,GAAG;QAEVC,QAAQ,KAAK,CAACD;QACd,MAAM,IAAIL,MAAM,CAAC,iBAAiB,EAAGK,EAAY,OAAO,EAAE;IAC5D,SAAU;QACR,MAAME,MAAM,AAAuB,MAAvB,OAAOZ,cAA8BA,YAAY,GAAG,KAAKC,KAAK,GAAG;QAC7EJ,QAAQ,WAAW,CAAC,YAAY,GAAG,GAAIe,AAAAA,CAAAA,MAAMb,KAAI,EAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACpE;AACF"}
|
|
@@ -44,6 +44,10 @@ export declare class Builder<S extends Spec = Spec> implements VSeedBuilder {
|
|
|
44
44
|
id: string;
|
|
45
45
|
alias: string;
|
|
46
46
|
}>;
|
|
47
|
+
/**
|
|
48
|
+
* @description 获取离散颜色图中 colorId 到最终颜色值的映射
|
|
49
|
+
*/
|
|
50
|
+
getColorValueMap: () => Record<string, string> | undefined;
|
|
47
51
|
/**
|
|
48
52
|
* @description 获取当前的 VSeed 输入数据
|
|
49
53
|
*/
|
|
@@ -3,7 +3,7 @@ import { buildSpec } from "./buildSpec.js";
|
|
|
3
3
|
import { build } from "./build.js";
|
|
4
4
|
import { prepare } from "./prepare.js";
|
|
5
5
|
import { intl } from "../../i18n/index.js";
|
|
6
|
-
import { getColorIdMap, getColorItems } from "./advanced/index.js";
|
|
6
|
+
import { getColorIdMap, getColorItems, getColorValueMap } from "./advanced/index.js";
|
|
7
7
|
class Builder {
|
|
8
8
|
_vseed;
|
|
9
9
|
_advancedVSeed = null;
|
|
@@ -24,6 +24,7 @@ class Builder {
|
|
|
24
24
|
buildAdvanced = ()=>buildAdvanced(this);
|
|
25
25
|
getColorItems = ()=>getColorItems(this);
|
|
26
26
|
getColorIdMap = ()=>getColorIdMap(this);
|
|
27
|
+
getColorValueMap = ()=>getColorValueMap(this);
|
|
27
28
|
get vseed() {
|
|
28
29
|
return this._vseed;
|
|
29
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder/builder/builder.js","sources":["../../../../src/builder/builder/builder.ts"],"sourcesContent":["import type {\n AdvancedPipe,\n AdvancedPipeline,\n AdvancedVSeed,\n ChartType,\n CustomThemeConfig,\n Locale,\n Spec,\n SpecPipe,\n SpecPipeline,\n VSeed,\n VSeedBuilder,\n} from 'src/types'\nimport { buildAdvanced } from './buildAdvanced'\nimport { buildSpec } from './buildSpec'\nimport { build } from './build'\nimport { prepare } from './prepare'\nimport { intl } from 'src/i18n'\nimport { getColorIdMap, getColorItems } from './advanced'\n\nexport class Builder<S extends Spec = Spec> implements VSeedBuilder {\n private _vseed: VSeed\n private _advancedVSeed: AdvancedVSeed | null = null\n private _spec: Spec | null = null\n private _performance: Record<string, string | number> = {}\n\n private _locale: Locale\n\n private _isPrepared: boolean = false\n\n /**\n * @description 初始化 Builder 实例\n */\n constructor(vseed: VSeed) {\n this._vseed = vseed\n this._locale = vseed.locale || intl.getLocale()\n }\n\n /**\n * @description 获取当前 Builder 使用的语言环境\n */\n get locale() {\n return this._locale\n }\n\n /**\n * @description 异步执行动态过滤器代码。在 build() 前调用,用于执行 dynamicFilter 中的 code。幂等方法,多次调用不会重复执行\n */\n prepare = async (): Promise<void> => prepare(this)\n\n /**\n * @description 生成最终的图表配置 (Spec)。这是最常用的核心方法。如果配置中包含 dynamicFilter code,需要先调用 prepare()\n */\n build = <T = S>(): T => build(this) as T\n\n /**\n * @description 将中间层配置 (AdvancedVSeed) 转换为最终 Spec。仅当你需要深度定制中间层配置时使用\n */\n buildSpec = <T = S>(advanced: AdvancedVSeed): T => buildSpec(this, advanced) as T\n\n /**\n * @description 生成中间层配置 (AdvancedVSeed),即图表模版。比原始 VSeed 更详细,暴露了更多图表细节\n */\n buildAdvanced = (): AdvancedVSeed | null => buildAdvanced(this)\n\n /**\n * @description 获取数据中涉及颜色的字段信息。常用于生成图表的图例或颜色筛选器 UI\n */\n getColorItems = () => getColorItems(this)\n\n /**\n * @description 获取颜色字段的详细映射表。Key 为颜色 ID,Value 为详细信息\n */\n getColorIdMap = () => getColorIdMap(this)\n\n /**\n * @description 获取当前的 VSeed 输入数据\n */\n get vseed() {\n return this._vseed\n }\n\n /**\n * @description 更新 VSeed 输入数据。更新后会清除 prepare() 的缓存状态\n */\n set vseed(value) {\n this._vseed = value\n this._isPrepared = false\n }\n\n /**\n * @description 获取 prepare() 状态\n */\n get isPrepared() {\n return this._isPrepared\n }\n\n /**\n * @description 设置 prepare() 状态\n */\n set isPrepared(value: boolean) {\n this._isPrepared = value\n }\n\n /**\n * @description 获取当前的 AdvancedVSeed 中间配置对象\n */\n get advancedVSeed() {\n return this._advancedVSeed\n }\n\n /**\n * @description 设置 AdvancedVSeed 中间配置对象。通常用于缓存或复用已有的中间配置\n */\n set advancedVSeed(value) {\n this._advancedVSeed = value\n }\n\n /**\n * @description 获取当前生成的最终 Spec 对象\n */\n get spec() {\n return this._spec\n }\n\n /**\n * @description 设置 Spec 对象。通常用于缓存\n */\n set spec(value) {\n this._spec = value\n }\n\n /**\n * @description 获取构建过程中的性能统计信息。包含各阶段耗时 (单位: ms)\n */\n get performance() {\n return this._performance\n }\n\n /**\n * @description 设置性能统计信息\n */\n set performance(value) {\n this._performance = value\n }\n\n /**\n * @description [内部方法] 获取指定图表类型的模版构建管线,用于调试 VSeed 到 AdvancedVSeed 的转换过程\n */\n static getAdvancedPipeline = (chartType: ChartType) => {\n const customPipe = Builder._customAdvancedPipe[chartType] as AdvancedPipe\n const originalPipeline = Builder._advancedPipelineMap[chartType] as AdvancedPipeline\n if (!originalPipeline) return originalPipeline\n\n const pipeline = [...originalPipeline]\n if (customPipe) {\n pipeline.push(customPipe)\n }\n return pipeline\n }\n\n /**\n * @description [内部方法] 获取指定图表类型的 Spec 构建管线,用于调试 AdvancedVSeed 到 Spec 的转换过程\n */\n static getSpecPipeline = (chartType: ChartType) => {\n const customPipe = Builder._customSpecPipe[chartType] as SpecPipe\n const originalPipeline = Builder._specPipelineMap[chartType] as SpecPipeline\n if (!originalPipeline) return originalPipeline\n\n const pipeline = [...originalPipeline]\n if (customPipe) {\n pipeline.push(customPipe)\n }\n return pipeline\n }\n\n /**\n * @description 获取指定主题的配置。不传 themeKey 默认返回 'light' 主题\n */\n static getTheme = (themeKey?: string): CustomThemeConfig => Builder._themeMap[themeKey || 'light']\n\n /**\n * @description 获取所有已注册的主题配置\n */\n static getThemeMap = (): Record<string, CustomThemeConfig> => Builder._themeMap\n\n /**\n * @description 静态工厂方法,用于便捷地创建 Builder 实例\n */\n static from = <T extends Spec = Spec>(vseed: VSeed) => new Builder<T>(vseed)\n\n /**\n * @description [扩展方法] 注册新图表类型的模版构建管线\n */\n static registerAdvancedPipeline = (chartType: ChartType, pipeline: AdvancedPipeline) => {\n Builder._advancedPipelineMap[chartType] = pipeline\n }\n\n /**\n * @description [扩展方法] 注册新图表类型的 Spec 构建管线\n */\n static registerSpecPipeline = (chartType: ChartType, pipeline: SpecPipeline) => {\n Builder._specPipelineMap[chartType] = pipeline\n }\n\n /**\n * @description [扩展方法] 修改现有图表的模版构建逻辑,插入自定义 Pipe 影响生成的 AdvancedVSeed\n */\n static updateAdvanced = (chartType: ChartType, pipe: AdvancedPipe) => {\n Builder._customAdvancedPipe[chartType] = pipe\n }\n\n /**\n * @description [扩展方法] 修改现有图表的 Spec 构建逻辑,插入自定义 Pipe 影响生成的最终 Spec\n */\n static updateSpec = (chartType: ChartType, pipe: SpecPipe) => {\n Builder._customSpecPipe[chartType] = pipe\n }\n\n /**\n * @description [扩展方法] 注册自定义主题\n */\n static registerTheme = (key: string, theme: CustomThemeConfig) => {\n Builder._themeMap[key] = theme\n }\n\n private static _advancedPipelineMap: Partial<Record<ChartType, AdvancedPipeline>> = {}\n private static _specPipelineMap: Partial<Record<ChartType, SpecPipeline>> = {}\n private static _customAdvancedPipe: Partial<Record<ChartType, AdvancedPipe>> = {}\n private static _customSpecPipe: Partial<Record<ChartType, SpecPipe>> = {}\n private static _themeMap: Record<string, CustomThemeConfig> = {}\n}\n"],"names":["Builder","vseed","intl","prepare","build","advanced","buildSpec","buildAdvanced","getColorItems","getColorIdMap","value","chartType","customPipe","originalPipeline","pipeline","themeKey","pipe","key","theme"],"mappings":";;;;;;AAoBO,MAAMA;IACH,OAAa;IACb,iBAAuC,KAAI;IAC3C,QAAqB,KAAI;IACzB,eAAgD,CAAC,EAAC;IAElD,QAAe;IAEf,cAAuB,MAAK;IAKpC,YAAYC,KAAY,CAAE;QACxB,IAAI,CAAC,MAAM,GAAGA;QACd,IAAI,CAAC,OAAO,GAAGA,MAAM,MAAM,IAAIC,KAAK,SAAS;IAC/C;IAKA,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO;IACrB;IAKA,UAAU,UAA2BC,QAAQ,IAAI,EAAC;IAKlD,QAAQ,IAAgBC,MAAM,IAAI,EAAM;IAKxC,YAAY,CAAQC,WAA+BC,UAAU,IAAI,EAAED,UAAc;IAKjF,gBAAgB,IAA4BE,cAAc,IAAI,EAAC;IAK/D,gBAAgB,IAAMC,cAAc,IAAI,EAAC;IAKzC,gBAAgB,IAAMC,cAAc,IAAI,EAAC;IAKzC,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM;IACpB;IAKA,IAAI,MAAMC,KAAK,EAAE;QACf,IAAI,CAAC,MAAM,GAAGA;QACd,IAAI,CAAC,WAAW,GAAG;IACrB;IAKA,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,WAAW;IACzB;IAKA,IAAI,WAAWA,KAAc,EAAE;QAC7B,IAAI,CAAC,WAAW,GAAGA;IACrB;IAKA,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,cAAc;IAC5B;IAKA,IAAI,cAAcA,KAAK,EAAE;QACvB,IAAI,CAAC,cAAc,GAAGA;IACxB;IAKA,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK;IACnB;IAKA,IAAI,KAAKA,KAAK,EAAE;QACd,IAAI,CAAC,KAAK,GAAGA;IACf;IAKA,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,YAAY;IAC1B;IAKA,IAAI,YAAYA,KAAK,EAAE;QACrB,IAAI,CAAC,YAAY,GAAGA;IACtB;IAKA,OAAO,sBAAsB,CAACC;QAC5B,MAAMC,
|
|
1
|
+
{"version":3,"file":"builder/builder/builder.js","sources":["../../../../src/builder/builder/builder.ts"],"sourcesContent":["import type {\n AdvancedPipe,\n AdvancedPipeline,\n AdvancedVSeed,\n ChartType,\n CustomThemeConfig,\n Locale,\n Spec,\n SpecPipe,\n SpecPipeline,\n VSeed,\n VSeedBuilder,\n} from 'src/types'\nimport { buildAdvanced } from './buildAdvanced'\nimport { buildSpec } from './buildSpec'\nimport { build } from './build'\nimport { prepare } from './prepare'\nimport { intl } from 'src/i18n'\nimport { getColorIdMap, getColorItems, getColorValueMap } from './advanced'\n\nexport class Builder<S extends Spec = Spec> implements VSeedBuilder {\n private _vseed: VSeed\n private _advancedVSeed: AdvancedVSeed | null = null\n private _spec: Spec | null = null\n private _performance: Record<string, string | number> = {}\n\n private _locale: Locale\n\n private _isPrepared: boolean = false\n\n /**\n * @description 初始化 Builder 实例\n */\n constructor(vseed: VSeed) {\n this._vseed = vseed\n this._locale = vseed.locale || intl.getLocale()\n }\n\n /**\n * @description 获取当前 Builder 使用的语言环境\n */\n get locale() {\n return this._locale\n }\n\n /**\n * @description 异步执行动态过滤器代码。在 build() 前调用,用于执行 dynamicFilter 中的 code。幂等方法,多次调用不会重复执行\n */\n prepare = async (): Promise<void> => prepare(this)\n\n /**\n * @description 生成最终的图表配置 (Spec)。这是最常用的核心方法。如果配置中包含 dynamicFilter code,需要先调用 prepare()\n */\n build = <T = S>(): T => build(this) as T\n\n /**\n * @description 将中间层配置 (AdvancedVSeed) 转换为最终 Spec。仅当你需要深度定制中间层配置时使用\n */\n buildSpec = <T = S>(advanced: AdvancedVSeed): T => buildSpec(this, advanced) as T\n\n /**\n * @description 生成中间层配置 (AdvancedVSeed),即图表模版。比原始 VSeed 更详细,暴露了更多图表细节\n */\n buildAdvanced = (): AdvancedVSeed | null => buildAdvanced(this)\n\n /**\n * @description 获取数据中涉及颜色的字段信息。常用于生成图表的图例或颜色筛选器 UI\n */\n getColorItems = () => getColorItems(this)\n\n /**\n * @description 获取颜色字段的详细映射表。Key 为颜色 ID,Value 为详细信息\n */\n getColorIdMap = () => getColorIdMap(this)\n\n /**\n * @description 获取离散颜色图中 colorId 到最终颜色值的映射\n */\n getColorValueMap = () => getColorValueMap(this)\n\n /**\n * @description 获取当前的 VSeed 输入数据\n */\n get vseed() {\n return this._vseed\n }\n\n /**\n * @description 更新 VSeed 输入数据。更新后会清除 prepare() 的缓存状态\n */\n set vseed(value) {\n this._vseed = value\n this._isPrepared = false\n }\n\n /**\n * @description 获取 prepare() 状态\n */\n get isPrepared() {\n return this._isPrepared\n }\n\n /**\n * @description 设置 prepare() 状态\n */\n set isPrepared(value: boolean) {\n this._isPrepared = value\n }\n\n /**\n * @description 获取当前的 AdvancedVSeed 中间配置对象\n */\n get advancedVSeed() {\n return this._advancedVSeed\n }\n\n /**\n * @description 设置 AdvancedVSeed 中间配置对象。通常用于缓存或复用已有的中间配置\n */\n set advancedVSeed(value) {\n this._advancedVSeed = value\n }\n\n /**\n * @description 获取当前生成的最终 Spec 对象\n */\n get spec() {\n return this._spec\n }\n\n /**\n * @description 设置 Spec 对象。通常用于缓存\n */\n set spec(value) {\n this._spec = value\n }\n\n /**\n * @description 获取构建过程中的性能统计信息。包含各阶段耗时 (单位: ms)\n */\n get performance() {\n return this._performance\n }\n\n /**\n * @description 设置性能统计信息\n */\n set performance(value) {\n this._performance = value\n }\n\n /**\n * @description [内部方法] 获取指定图表类型的模版构建管线,用于调试 VSeed 到 AdvancedVSeed 的转换过程\n */\n static getAdvancedPipeline = (chartType: ChartType) => {\n const customPipe = Builder._customAdvancedPipe[chartType] as AdvancedPipe\n const originalPipeline = Builder._advancedPipelineMap[chartType] as AdvancedPipeline\n if (!originalPipeline) return originalPipeline\n\n const pipeline = [...originalPipeline]\n if (customPipe) {\n pipeline.push(customPipe)\n }\n return pipeline\n }\n\n /**\n * @description [内部方法] 获取指定图表类型的 Spec 构建管线,用于调试 AdvancedVSeed 到 Spec 的转换过程\n */\n static getSpecPipeline = (chartType: ChartType) => {\n const customPipe = Builder._customSpecPipe[chartType] as SpecPipe\n const originalPipeline = Builder._specPipelineMap[chartType] as SpecPipeline\n if (!originalPipeline) return originalPipeline\n\n const pipeline = [...originalPipeline]\n if (customPipe) {\n pipeline.push(customPipe)\n }\n return pipeline\n }\n\n /**\n * @description 获取指定主题的配置。不传 themeKey 默认返回 'light' 主题\n */\n static getTheme = (themeKey?: string): CustomThemeConfig => Builder._themeMap[themeKey || 'light']\n\n /**\n * @description 获取所有已注册的主题配置\n */\n static getThemeMap = (): Record<string, CustomThemeConfig> => Builder._themeMap\n\n /**\n * @description 静态工厂方法,用于便捷地创建 Builder 实例\n */\n static from = <T extends Spec = Spec>(vseed: VSeed) => new Builder<T>(vseed)\n\n /**\n * @description [扩展方法] 注册新图表类型的模版构建管线\n */\n static registerAdvancedPipeline = (chartType: ChartType, pipeline: AdvancedPipeline) => {\n Builder._advancedPipelineMap[chartType] = pipeline\n }\n\n /**\n * @description [扩展方法] 注册新图表类型的 Spec 构建管线\n */\n static registerSpecPipeline = (chartType: ChartType, pipeline: SpecPipeline) => {\n Builder._specPipelineMap[chartType] = pipeline\n }\n\n /**\n * @description [扩展方法] 修改现有图表的模版构建逻辑,插入自定义 Pipe 影响生成的 AdvancedVSeed\n */\n static updateAdvanced = (chartType: ChartType, pipe: AdvancedPipe) => {\n Builder._customAdvancedPipe[chartType] = pipe\n }\n\n /**\n * @description [扩展方法] 修改现有图表的 Spec 构建逻辑,插入自定义 Pipe 影响生成的最终 Spec\n */\n static updateSpec = (chartType: ChartType, pipe: SpecPipe) => {\n Builder._customSpecPipe[chartType] = pipe\n }\n\n /**\n * @description [扩展方法] 注册自定义主题\n */\n static registerTheme = (key: string, theme: CustomThemeConfig) => {\n Builder._themeMap[key] = theme\n }\n\n private static _advancedPipelineMap: Partial<Record<ChartType, AdvancedPipeline>> = {}\n private static _specPipelineMap: Partial<Record<ChartType, SpecPipeline>> = {}\n private static _customAdvancedPipe: Partial<Record<ChartType, AdvancedPipe>> = {}\n private static _customSpecPipe: Partial<Record<ChartType, SpecPipe>> = {}\n private static _themeMap: Record<string, CustomThemeConfig> = {}\n}\n"],"names":["Builder","vseed","intl","prepare","build","advanced","buildSpec","buildAdvanced","getColorItems","getColorIdMap","getColorValueMap","value","chartType","customPipe","originalPipeline","pipeline","themeKey","pipe","key","theme"],"mappings":";;;;;;AAoBO,MAAMA;IACH,OAAa;IACb,iBAAuC,KAAI;IAC3C,QAAqB,KAAI;IACzB,eAAgD,CAAC,EAAC;IAElD,QAAe;IAEf,cAAuB,MAAK;IAKpC,YAAYC,KAAY,CAAE;QACxB,IAAI,CAAC,MAAM,GAAGA;QACd,IAAI,CAAC,OAAO,GAAGA,MAAM,MAAM,IAAIC,KAAK,SAAS;IAC/C;IAKA,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO;IACrB;IAKA,UAAU,UAA2BC,QAAQ,IAAI,EAAC;IAKlD,QAAQ,IAAgBC,MAAM,IAAI,EAAM;IAKxC,YAAY,CAAQC,WAA+BC,UAAU,IAAI,EAAED,UAAc;IAKjF,gBAAgB,IAA4BE,cAAc,IAAI,EAAC;IAK/D,gBAAgB,IAAMC,cAAc,IAAI,EAAC;IAKzC,gBAAgB,IAAMC,cAAc,IAAI,EAAC;IAKzC,mBAAmB,IAAMC,iBAAiB,IAAI,EAAC;IAK/C,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM;IACpB;IAKA,IAAI,MAAMC,KAAK,EAAE;QACf,IAAI,CAAC,MAAM,GAAGA;QACd,IAAI,CAAC,WAAW,GAAG;IACrB;IAKA,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,WAAW;IACzB;IAKA,IAAI,WAAWA,KAAc,EAAE;QAC7B,IAAI,CAAC,WAAW,GAAGA;IACrB;IAKA,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,cAAc;IAC5B;IAKA,IAAI,cAAcA,KAAK,EAAE;QACvB,IAAI,CAAC,cAAc,GAAGA;IACxB;IAKA,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK;IACnB;IAKA,IAAI,KAAKA,KAAK,EAAE;QACd,IAAI,CAAC,KAAK,GAAGA;IACf;IAKA,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,YAAY;IAC1B;IAKA,IAAI,YAAYA,KAAK,EAAE;QACrB,IAAI,CAAC,YAAY,GAAGA;IACtB;IAKA,OAAO,sBAAsB,CAACC;QAC5B,MAAMC,aAAab,QAAQ,mBAAmB,CAACY,UAAU;QACzD,MAAME,mBAAmBd,QAAQ,oBAAoB,CAACY,UAAU;QAChE,IAAI,CAACE,kBAAkB,OAAOA;QAE9B,MAAMC,WAAW;eAAID;SAAiB;QACtC,IAAID,YACFE,SAAS,IAAI,CAACF;QAEhB,OAAOE;IACT,EAAC;IAKD,OAAO,kBAAkB,CAACH;QACxB,MAAMC,aAAab,QAAQ,eAAe,CAACY,UAAU;QACrD,MAAME,mBAAmBd,QAAQ,gBAAgB,CAACY,UAAU;QAC5D,IAAI,CAACE,kBAAkB,OAAOA;QAE9B,MAAMC,WAAW;eAAID;SAAiB;QACtC,IAAID,YACFE,SAAS,IAAI,CAACF;QAEhB,OAAOE;IACT,EAAC;IAKD,OAAO,WAAW,CAACC,WAAyChB,QAAQ,SAAS,CAACgB,YAAY,QAAQ;IAKlG,OAAO,cAAc,IAAyChB,QAAQ,SAAS;IAK/E,OAAO,OAAO,CAAwBC,QAAiB,IAAID,QAAWC,OAAM;IAK5E,OAAO,2BAA2B,CAACW,WAAsBG;QACvDf,QAAQ,oBAAoB,CAACY,UAAU,GAAGG;IAC5C,EAAC;IAKD,OAAO,uBAAuB,CAACH,WAAsBG;QACnDf,QAAQ,gBAAgB,CAACY,UAAU,GAAGG;IACxC,EAAC;IAKD,OAAO,iBAAiB,CAACH,WAAsBK;QAC7CjB,QAAQ,mBAAmB,CAACY,UAAU,GAAGK;IAC3C,EAAC;IAKD,OAAO,aAAa,CAACL,WAAsBK;QACzCjB,QAAQ,eAAe,CAACY,UAAU,GAAGK;IACvC,EAAC;IAKD,OAAO,gBAAgB,CAACC,KAAaC;QACnCnB,QAAQ,SAAS,CAACkB,IAAI,GAAGC;IAC3B,EAAC;IAED,OAAe,uBAAqE,CAAC,EAAC;IACtF,OAAe,mBAA6D,CAAC,EAAC;IAC9E,OAAe,sBAAgE,CAAC,EAAC;IACjF,OAAe,kBAAwD,CAAC,EAAC;IACzE,OAAe,YAA+C,CAAC,EAAC;AAClE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataSelector/selector.js","sources":["../../../src/dataSelector/selector.ts"],"sourcesContent":["import type { Datum } from 'src/types'\nimport type {\n ChartDynamicFilter,\n PartialDatumRes,\n DimensionSelector,\n FieldSelector,\n MeasureSelector,\n PartialDatumSelector,\n Selector,\n Selectors,\n RowWithFieldRes,\n TableDynamicFilter,\n ValueSelector,\n ValueDynamicFilter,\n} from '../types/dataSelector'\nimport { omit } from 'remeda'\nimport { executeFilterCode } from 'src/pipeline/utils/sandbox'\nimport { InnerRowIndex } from 'src/dataReshape'\n\nexport type DynamicFilter = TableDynamicFilter | ChartDynamicFilter | ValueDynamicFilter\nexport type DynamicFilterResult = RowWithFieldRes[] | PartialDatumRes[] | number | string\n\n/**\n * 判断两个数字是否“近似相等”\n */\nfunction nearlyEqual(a: number, b: number, epsilon = 1e-8) {\n // NaN 直接不相等\n if (Number.isNaN(a) || Number.isNaN(b)) return false\n // 引用同一个数 或 完全相等\n if (a === b) return true\n const diff = Math.abs(a - b)\n return diff <= epsilon\n}\n\nexport const selector = (\n vchartDatum: Datum,\n selector: Selector | Selectors | undefined | null,\n selectorMode: 'And' | 'Or' = 'And',\n) => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selector) {\n return true\n }\n\n // 过滤掉 vchart 相关字段\n const vchartKeys = Object.keys(vchartDatum).filter((k) => k.toLocaleLowerCase().startsWith('__vchart'))\n const datum = omit(vchartDatum, vchartKeys) as Datum\n\n // 统一处理选择器为数组\n const selectors = (Array.isArray(selector) ? selector : [selector]) as Selectors\n\n return selectors[selectorMode === 'And' ? 'every' : 'some']((selector) => {\n // 1. 字符串或数字\n if (isValueSelector(selector)) {\n return selectByValue(selector, datum)\n }\n\n // 2. 字段选择器(优先于 MeasureSelector/DimensionSelector 判断,因为字段选择器也有 field 属性)\n else if (isFieldSelector(selector)) {\n return selectByField(selector, datum)\n }\n\n // 3. 指标选择器\n else if (isMeasureSelector(selector)) {\n return selectByMeasure(selector, datum)\n }\n // 4. 维度选择器\n else if (isDimensionSelector(selector)) {\n return selectByDmension(selector, datum)\n }\n // 5. 部分数据对象选择器\n else if (isPartialDatumSelector(selector)) {\n return selectByPartial(selector, datum)\n }\n\n return false\n })\n}\n\nexport const isValueSelector = (selector: Selector): selector is ValueSelector => {\n return typeof selector === 'string' || typeof selector === 'number'\n}\n\nexport const isPartialDatumSelector = (selector: Selector): selector is PartialDatumSelector => {\n return typeof selector === 'object' && selector !== null\n}\n\n/**\n * 判断是否为字段选择器\n * @description 字段选择器只有 field 属性,没有 operator/op/value\n */\nexport const isFieldSelector = (selector: Selector): selector is FieldSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n !('operator' in selector) &&\n !('op' in selector) &&\n !('value' in selector)\n )\n}\n\nexport const isMeasureSelector = (selector: Selector): selector is MeasureSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.operator as string) ||\n ['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.op as string))\n )\n}\n\nexport const isDimensionSelector = (selector: Selector): selector is DimensionSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['in', 'not in'].includes(selector.operator as string) || ['in', 'not in'].includes(selector.op as string))\n )\n}\n\nexport const selectByMeasure = (selector: MeasureSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n\n switch (op) {\n case '=':\n if (\n String(datum[selector.field]) === String(selectorValueArr[0]) ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '==':\n if (datum[selector.field] === selectorValueArr[0]) {\n return true\n }\n break\n case '!=':\n if (datum[selector.field] !== selectorValueArr[0]) {\n return true\n }\n break\n case '>':\n if (\n datum[selector.field] > selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<':\n if (\n datum[selector.field] < selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '>=':\n if (\n datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<=':\n if (\n datum[selector.field] <= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case 'between':\n if (\n Array.isArray(selector.value) &&\n (datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))) &&\n (datum[selector.field] <= selectorValueArr[1] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[1])))\n ) {\n return true\n }\n break\n }\n return false\n}\n\nexport const selectByDmension = (selector: DimensionSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n switch (op) {\n case 'in':\n if (selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n case 'not in':\n if (!selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n }\n\n return false\n}\n\n/**\n * 通过字段名选择\n * @description 检查 datum 是否包含指定字段(用于列级选择)\n */\nexport const selectByField = (selector: FieldSelector, datum: Datum) => {\n const fields = Array.isArray(selector.field) ? selector.field : [selector.field]\n const datumKeys = Object.keys(datum)\n\n // 检查 datum 的 keys 中是否包含任一指定字段\n return fields.some((field) => datumKeys.includes(field))\n}\n\n/**\n * 检查给定的字段是否与 FieldSelector 匹配\n */\nexport const matchesFieldSelector = (field: string, fieldSelector: FieldSelector): boolean => {\n const fields = Array.isArray(fieldSelector.field) ? fieldSelector.field : [fieldSelector.field]\n return fields.includes(field)\n}\n\nexport const selectByPartial = (selector: PartialDatumSelector, datum: Datum) => {\n return Object.keys(selector).every((key) => datum[key] === selector[key])\n}\n\nexport const selectByValue = (selector: ValueSelector, datum: Datum) => {\n return Object.values(datum).some((v) => v === selector)\n}\n\nconst matchesCellSelector = (cell: Datum, filterRes: RowWithFieldRes) => {\n if (filterRes[InnerRowIndex] !== cell[InnerRowIndex]) return false\n return filterRes.field === '*' || Object.keys(cell).includes(filterRes.field)\n}\n\nconst matchesDatum = (target: Datum, candidate: Datum) => {\n return Object.keys(candidate).every((key) => target[key] === candidate[key])\n}\n\n/**\n * 公共方法:检查是否为动态过滤器结构\n */\nconst isDynamicFilterLike = (selector: any, expectedTypes: string[]): boolean => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'type' in selector &&\n expectedTypes.includes(selector.type) &&\n 'code' in selector &&\n typeof selector.code === 'string'\n )\n}\n\n/**\n * 识别是否为row-with-field动态过滤器\n */\nexport const isRowWithFieldDynamicFilter = (selector: any): selector is TableDynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field'])\n}\n\n/**\n * 识别是否为数值动态过滤器(用于标注线等场景)\n */\nexport const isValueDynamicFilter = (selector: any): selector is ValueDynamicFilter => {\n return isDynamicFilterLike(selector, ['value'])\n}\n\n/**\n * 识别是否为动态过滤器(通用判断,包含所有类型的动态过滤器)\n */\nexport const isDynamicFilter = (selector: any): selector is DynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field', 'value'])\n}\n\n/**\n * 验证动态过滤器执行结果的类型兼容性\n * @description\n * 在主线程中对 Worker 返回值进行类型特定的验证\n * - TableDynamicFilter: 必须返回包含 __row_index 和 field 的对象数组\n * - ChartDynamicFilter: 必须返回任意对象数组\n * - ValueDynamicFilter: 必须返回 number | string\n *\n * @param result Worker 返回的原始结果\n * @param filter 动态过滤器配置\n * @returns 验证是否通过\n * @throws 当验证失败时抛出 TypeError\n */\nconst validateFilterResult = (result: any, filter: DynamicFilter): void => {\n // ValueDynamicFilter:必须返回 number | string\n if (isValueDynamicFilter(filter)) {\n if (typeof result !== 'number' && typeof result !== 'string') {\n throw new TypeError(\n `ValueDynamicFilter must return a number or string, but got: ${typeof result}. ` + `Code: \"${filter.code}\"`,\n )\n }\n return\n }\n\n // TableDynamicFilter 和 ChartDynamicFilter:必须返回对象数组\n if (!Array.isArray(result)) {\n throw new TypeError(\n `${isRowWithFieldDynamicFilter(filter) ? 'TableDynamicFilter' : 'ChartDynamicFilter'} must return an array, ` +\n `but got: ${typeof result}. Code: \"${filter.code}\"`,\n )\n }\n\n // TableDynamicFilter:检查数组元素结构\n if (isRowWithFieldDynamicFilter(filter)) {\n for (let i = 0; i < result.length; i++) {\n const item = result[i]\n if (typeof item !== 'object' || item === null) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must be an object, got: ${typeof item}`)\n }\n if (!(InnerRowIndex in item) && '__row_index' in item === false) {\n throw new TypeError(\n `TableDynamicFilter array element at index ${i} must contain __row_index or InnerRowIndex field`,\n )\n }\n if (!('field' in item)) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must contain 'field' field`)\n }\n }\n }\n}\n\n/**\n * 执行动态过滤器代码,获取匹配结果\n * @description\n * 阶段1:执行阶段 - 一次性执行 dynamicFilter.code,获取所有匹配结果\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string\n *\n * @param filter 动态过滤器配置\n * @param allData 完整数据集\n * @returns 执行结果数组或标量值\n */\nexport const executeDynamicFilter = async (\n filter: DynamicFilter,\n allData: Datum[],\n): Promise<{ success: boolean; data: DynamicFilterResult; error?: string }> => {\n try {\n const { success, data, error } = await executeFilterCode({\n code: filter.code,\n data: allData,\n })\n\n if (!success) {\n // eslint-disable-next-line no-console\n console.warn('[vseed] Dynamic filter execution failed:', error)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error,\n }\n }\n\n // 主线程验证:根据过滤器类型进行特定检查\n try {\n validateFilterResult(data, filter)\n } catch (validationError) {\n // eslint-disable-next-line no-console\n console.error('[vseed] Dynamic filter result validation failed:', validationError)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: validationError instanceof Error ? validationError.message : String(validationError),\n }\n }\n\n return {\n success,\n data: data as DynamicFilterResult,\n }\n } catch (error) {\n // 捕获所有可能的异常:\n // - Worker 不支持\n // - Worker 池初始化/获取失败\n // - validateCodeSafety 验证失败\n // - 数据验证失败\n const errorMessage = error instanceof Error ? error.message : String(error)\n // eslint-disable-next-line no-console\n console.error('[vseed] Dynamic filter execution threw exception:', errorMessage)\n\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: errorMessage,\n }\n }\n}\n\n/**\n * 匹配动态过滤器结果\n * @description\n * 阶段2:匹配阶段 - 判断当前 datum/cell 是否在执行结果中\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格场景:检查 { row, field } 是否在 CellSelector[] 中\n * - 图表场景:检查 datum 的维度值是否匹配 PartialDatumSelector[] 中任一项\n * - 数值场景:不适用(ValueDynamicFilter返回标量值,不用于匹配)\n *\n * @param result 动态过滤器执行结果(CellSelector[] 或 PartialDatumSelector[],不包括 ValueDynamicFilter)\n * @param datum 当前数据项\n * @param selectorType 选择器类型(用于区分表格和图表动态过滤器)\n * @returns 是否匹配(OR 策略)\n */\nexport const matchDynamicFilterResult = (\n result: DynamicFilterResult,\n datum: Datum,\n selectorType: 'table' | 'chart' = 'table',\n): boolean => {\n // ValueDynamicFilter 不应该通过这个函数处理\n if (typeof result === 'number' || typeof result === 'string') {\n throw new Error('matchDynamicFilterResult does not support ValueDynamicFilter results')\n }\n\n if (selectorType === 'table') {\n return result.some((item) => {\n return matchesCellSelector(datum, item as RowWithFieldRes)\n })\n }\n return result.some((item) => {\n return matchesDatum(datum, item as PartialDatumSelector)\n })\n}\n\n/**\n * 带有动态过滤器支持的选择器\n * @description\n * 处理流程(两阶段设计):\n *\n * 阶段1 - 执行(Execute):\n * - 在 prepare() 阶段执行,结果写入 dynamicFilter.result\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string(用于读取,不用于匹配)\n *\n * 阶段2 - 匹配(Match):\n * - 读取 dynamicFilter.result\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格:判断 { row, field } 是否在 CellSelector[] 中\n * - 图表:判断 datum 是否匹配 PartialDatumSelector[] 中任一项\n * - 数值:不用于匹配,直接返回 false(数值过滤器在主要用于标注线值,不用于行列选择)\n *\n * @param vchartDatum 单个数据项\n * @param selectorConfig 选择器配置(可包含 DynamicFilter)\n * @param defaultSelector 传统选择器(仅在 DynamicFilter 无结果且有 fallback 时使用)\n * @returns 该数据项是否符合选择条件\n */\nexport const selectorWithDynamicFilter = (\n vchartDatum: Datum,\n selectorConfig: DynamicFilter,\n defaultSelector?: Selector | Selector[] | null,\n): boolean => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selectorConfig) {\n return true\n }\n\n // ValueDynamicFilter 不用于选择,直接返回 false\n if (isValueDynamicFilter(selectorConfig)) {\n if (selectorConfig.fallback) {\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n }\n\n const selectorType = isRowWithFieldDynamicFilter(selectorConfig) ? 'table' : 'chart'\n\n // 优先使用预先执行的结果\n if (selectorConfig.result?.success && selectorConfig.result.data) {\n return matchDynamicFilterResult(selectorConfig.result.data, vchartDatum, selectorType)\n }\n\n if (selectorConfig.fallback) {\n // 如果有 fallback,使用传统 selector 进行匹配\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n\n // 没有结果也没有 fallback,返回 false\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n}\n"],"names":["nearlyEqual","a","b","epsilon","Number","diff","Math","selector","vchartDatum","selectorMode","vchartKeys","Object","k","datum","omit","selectors","Array","isValueSelector","selectByValue","isFieldSelector","selectByField","isMeasureSelector","selectByMeasure","isDimensionSelector","selectByDmension","isPartialDatumSelector","selectByPartial","op","selectorValueArr","String","fields","datumKeys","field","matchesFieldSelector","fieldSelector","key","v","matchesCellSelector","cell","filterRes","InnerRowIndex","matchesDatum","target","candidate","isDynamicFilterLike","expectedTypes","isRowWithFieldDynamicFilter","isValueDynamicFilter","isDynamicFilter","validateFilterResult","result","filter","TypeError","i","item","executeDynamicFilter","allData","success","data","error","executeFilterCode","console","validationError","Error","errorMessage","matchDynamicFilterResult","selectorType","selectorWithDynamicFilter","selectorConfig","defaultSelector","fallbackSelector"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dataSelector/selector.js","sources":["../../../src/dataSelector/selector.ts"],"sourcesContent":["import type { Datum } from 'src/types'\nimport type {\n ChartDynamicFilter,\n PartialDatumRes,\n DimensionSelector,\n FieldSelector,\n MeasureSelector,\n PartialDatumSelector,\n Selector,\n Selectors,\n RowWithFieldRes,\n TableDynamicFilter,\n ValueSelector,\n ValueDynamicFilter,\n} from '../types/dataSelector'\nimport { omit } from 'remeda'\nimport { executeFilterCode } from 'src/pipeline/utils/sandbox'\nimport { InnerRowIndex } from 'src/dataReshape'\n\nexport type DynamicFilter = TableDynamicFilter | ChartDynamicFilter | ValueDynamicFilter\nexport type DynamicFilterResult = RowWithFieldRes[] | PartialDatumRes[] | number | string\n\n/**\n * 判断两个数字是否“近似相等”\n */\nfunction nearlyEqual(a: number, b: number, epsilon = 1e-8) {\n // NaN 直接不相等\n if (Number.isNaN(a) || Number.isNaN(b)) return false\n // 引用同一个数 或 完全相等\n if (a === b) return true\n const diff = Math.abs(a - b)\n return diff <= epsilon\n}\n\nexport const selector = (\n vchartDatum: Datum,\n selector: Selector | Selectors | undefined | null,\n selectorMode: 'And' | 'Or' = 'And',\n) => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selector) {\n return true\n }\n\n // 过滤掉 vchart 相关字段\n const vchartKeys = Object.keys(vchartDatum).filter((k) => k.toLocaleLowerCase().startsWith('__vchart'))\n const datum = omit(vchartDatum, vchartKeys) as Datum\n\n // 统一处理选择器为数组\n const selectors = (Array.isArray(selector) ? selector : [selector]) as Selectors\n\n return selectors[selectorMode === 'And' ? 'every' : 'some']((selector) => {\n // 1. 字符串或数字\n if (isValueSelector(selector)) {\n return selectByValue(selector, datum)\n }\n\n // 2. 字段选择器(优先于 MeasureSelector/DimensionSelector 判断,因为字段选择器也有 field 属性)\n else if (isFieldSelector(selector)) {\n return selectByField(selector, datum)\n }\n\n // 3. 指标选择器\n else if (isMeasureSelector(selector)) {\n return selectByMeasure(selector, datum)\n }\n // 4. 维度选择器\n else if (isDimensionSelector(selector)) {\n return selectByDmension(selector, datum)\n }\n // 5. 部分数据对象选择器\n else if (isPartialDatumSelector(selector)) {\n return selectByPartial(selector, datum)\n }\n\n return false\n })\n}\n\nexport const isValueSelector = (selector: Selector): selector is ValueSelector => {\n return typeof selector === 'string' || typeof selector === 'number'\n}\n\nexport const isPartialDatumSelector = (selector: Selector): selector is PartialDatumSelector => {\n return typeof selector === 'object' && selector !== null\n}\n\n/**\n * 判断是否为字段选择器\n * @description 字段选择器只有 field 属性,没有 operator/op/value\n */\nexport const isFieldSelector = (selector: Selector): selector is FieldSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n !('operator' in selector) &&\n !('op' in selector) &&\n !('value' in selector)\n )\n}\n\nexport const isMeasureSelector = (selector: Selector): selector is MeasureSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.operator as string) ||\n ['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.op as string))\n )\n}\n\nexport const isDimensionSelector = (selector: Selector): selector is DimensionSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['in', 'not in'].includes(selector.operator as string) || ['in', 'not in'].includes(selector.op as string))\n )\n}\n\nexport const selectByMeasure = (selector: MeasureSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n\n switch (op) {\n case '=':\n if (\n String(datum[selector.field]) === String(selectorValueArr[0]) ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '==':\n if (datum[selector.field] === selectorValueArr[0]) {\n return true\n }\n break\n case '!=':\n if (datum[selector.field] !== selectorValueArr[0]) {\n return true\n }\n break\n case '>':\n if (\n datum[selector.field] > selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<':\n if (\n datum[selector.field] < selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '>=':\n if (\n datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<=':\n if (\n datum[selector.field] <= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case 'between':\n if (\n Array.isArray(selector.value) &&\n (datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))) &&\n (datum[selector.field] <= selectorValueArr[1] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[1])))\n ) {\n return true\n }\n break\n }\n return false\n}\n\nexport const selectByDmension = (selector: DimensionSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n switch (op) {\n case 'in':\n if (selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n case 'not in':\n if (!selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n }\n\n return false\n}\n\n/**\n * 通过字段名选择\n * @description 检查 datum 是否包含指定字段(用于列级选择)\n */\nexport const selectByField = (selector: FieldSelector, datum: Datum) => {\n const fields = Array.isArray(selector.field) ? selector.field : [selector.field]\n const datumKeys = Object.keys(datum)\n\n // 检查 datum 的 keys 中是否包含任一指定字段\n return fields.some((field) => datumKeys.includes(field))\n}\n\n/**\n * 检查给定的字段是否与 FieldSelector 匹配\n */\nexport const matchesFieldSelector = (field: string, fieldSelector: FieldSelector): boolean => {\n const fields = Array.isArray(fieldSelector.field) ? fieldSelector.field : [fieldSelector.field]\n return fields.includes(field)\n}\n\nexport const selectByPartial = (selector: PartialDatumSelector, datum: Datum) => {\n return Object.keys(selector).every((key) => datum[key] === selector[key])\n}\n\nexport const selectByValue = (selector: ValueSelector, datum: Datum) => {\n return Object.values(datum).some((v) => v === selector)\n}\n\nconst matchesCellSelector = (cell: Datum, filterRes: RowWithFieldRes) => {\n if (filterRes[InnerRowIndex] !== cell[InnerRowIndex]) return false\n return filterRes.field === '*' || Object.keys(cell).includes(filterRes.field)\n}\n\nconst matchesDatum = (target: Datum, candidate: Datum) => {\n return Object.keys(candidate).every((key) => target[key] === candidate[key])\n}\n\n/**\n * 公共方法:检查是否为动态过滤器结构\n */\nconst isDynamicFilterLike = (selector: any, expectedTypes: string[]): boolean => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'type' in selector &&\n expectedTypes.includes(selector.type) &&\n 'code' in selector &&\n typeof selector.code === 'string'\n )\n}\n\n/**\n * 识别是否为row-with-field动态过滤器\n */\nexport const isRowWithFieldDynamicFilter = (selector: any): selector is TableDynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field'])\n}\n\n/**\n * 识别是否为数值动态过滤器(用于标注线等场景)\n */\nexport const isValueDynamicFilter = (selector: any): selector is ValueDynamicFilter => {\n return isDynamicFilterLike(selector, ['value'])\n}\n\n/**\n * 识别是否为动态过滤器(通用判断,包含所有类型的动态过滤器)\n */\nexport const isDynamicFilter = (selector: any): selector is DynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field', 'value'])\n}\n\n/**\n * 验证动态过滤器执行结果的类型兼容性\n * @description\n * 在主线程中对 Worker 返回值进行类型特定的验证\n * - TableDynamicFilter: 必须返回包含 __row_index 和 field 的对象数组\n * - ChartDynamicFilter: 必须返回任意对象数组\n * - ValueDynamicFilter: 必须返回 number | string\n *\n * @param result Worker 返回的原始结果\n * @param filter 动态过滤器配置\n * @returns 验证是否通过\n * @throws 当验证失败时抛出 TypeError\n */\nconst validateFilterResult = (result: any, filter: DynamicFilter): void => {\n // ValueDynamicFilter:必须返回 number | string\n if (isValueDynamicFilter(filter)) {\n if (typeof result !== 'number' && typeof result !== 'string') {\n throw new TypeError(\n `ValueDynamicFilter must return a number or string, but got: ${typeof result}. ` + `Code: \"${filter.code}\"`,\n )\n }\n return\n }\n\n // TableDynamicFilter 和 ChartDynamicFilter:必须返回对象数组\n if (!Array.isArray(result)) {\n throw new TypeError(\n `${isRowWithFieldDynamicFilter(filter) ? 'TableDynamicFilter' : 'ChartDynamicFilter'} must return an array, ` +\n `but got: ${typeof result}. Code: \"${filter.code}\"`,\n )\n }\n\n // TableDynamicFilter:检查数组元素结构\n if (isRowWithFieldDynamicFilter(filter)) {\n for (let i = 0; i < result.length; i++) {\n const item = result[i]\n if (typeof item !== 'object' || item === null) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must be an object, got: ${typeof item}`)\n }\n if (!(InnerRowIndex in item) && '__row_index' in item === false) {\n throw new TypeError(\n `TableDynamicFilter array element at index ${i} must contain __row_index or InnerRowIndex field`,\n )\n }\n if (!('field' in item)) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must contain 'field' field`)\n }\n }\n }\n}\n\n/**\n * 执行动态过滤器代码,获取匹配结果\n * @description\n * 阶段1:执行阶段 - 一次性执行 dynamicFilter.code,获取所有匹配结果\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string\n *\n * @param filter 动态过滤器配置\n * @param allData 完整数据集\n * @returns 执行结果数组或标量值\n */\nexport const executeDynamicFilter = async (\n filter: DynamicFilter,\n allData: Datum[],\n): Promise<{ success: boolean; data: DynamicFilterResult; error?: string }> => {\n try {\n const { success, data, error } = await executeFilterCode({\n code: filter.code,\n data: allData,\n })\n\n if (!success) {\n // oxlint-disable-next-line no-console\n console.warn('[vseed] Dynamic filter execution failed:', error)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error,\n }\n }\n\n // 主线程验证:根据过滤器类型进行特定检查\n try {\n validateFilterResult(data, filter)\n } catch (validationError) {\n // oxlint-disable-next-line no-console\n console.error('[vseed] Dynamic filter result validation failed:', validationError)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: validationError instanceof Error ? validationError.message : String(validationError),\n }\n }\n\n return {\n success,\n data: data as DynamicFilterResult,\n }\n } catch (error) {\n // 捕获所有可能的异常:\n // - Worker 不支持\n // - Worker 池初始化/获取失败\n // - validateCodeSafety 验证失败\n // - 数据验证失败\n const errorMessage = error instanceof Error ? error.message : String(error)\n // oxlint-disable-next-line no-console\n console.error('[vseed] Dynamic filter execution threw exception:', errorMessage)\n\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: errorMessage,\n }\n }\n}\n\n/**\n * 匹配动态过滤器结果\n * @description\n * 阶段2:匹配阶段 - 判断当前 datum/cell 是否在执行结果中\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格场景:检查 { row, field } 是否在 CellSelector[] 中\n * - 图表场景:检查 datum 的维度值是否匹配 PartialDatumSelector[] 中任一项\n * - 数值场景:不适用(ValueDynamicFilter返回标量值,不用于匹配)\n *\n * @param result 动态过滤器执行结果(CellSelector[] 或 PartialDatumSelector[],不包括 ValueDynamicFilter)\n * @param datum 当前数据项\n * @param selectorType 选择器类型(用于区分表格和图表动态过滤器)\n * @returns 是否匹配(OR 策略)\n */\nexport const matchDynamicFilterResult = (\n result: DynamicFilterResult,\n datum: Datum,\n selectorType: 'table' | 'chart' = 'table',\n): boolean => {\n // ValueDynamicFilter 不应该通过这个函数处理\n if (typeof result === 'number' || typeof result === 'string') {\n throw new Error('matchDynamicFilterResult does not support ValueDynamicFilter results')\n }\n\n if (selectorType === 'table') {\n return result.some((item) => {\n return matchesCellSelector(datum, item as RowWithFieldRes)\n })\n }\n return result.some((item) => {\n return matchesDatum(datum, item as PartialDatumSelector)\n })\n}\n\n/**\n * 带有动态过滤器支持的选择器\n * @description\n * 处理流程(两阶段设计):\n *\n * 阶段1 - 执行(Execute):\n * - 在 prepare() 阶段执行,结果写入 dynamicFilter.result\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string(用于读取,不用于匹配)\n *\n * 阶段2 - 匹配(Match):\n * - 读取 dynamicFilter.result\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格:判断 { row, field } 是否在 CellSelector[] 中\n * - 图表:判断 datum 是否匹配 PartialDatumSelector[] 中任一项\n * - 数值:不用于匹配,直接返回 false(数值过滤器在主要用于标注线值,不用于行列选择)\n *\n * @param vchartDatum 单个数据项\n * @param selectorConfig 选择器配置(可包含 DynamicFilter)\n * @param defaultSelector 传统选择器(仅在 DynamicFilter 无结果且有 fallback 时使用)\n * @returns 该数据项是否符合选择条件\n */\nexport const selectorWithDynamicFilter = (\n vchartDatum: Datum,\n selectorConfig: DynamicFilter,\n defaultSelector?: Selector | Selector[] | null,\n): boolean => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selectorConfig) {\n return true\n }\n\n // ValueDynamicFilter 不用于选择,直接返回 false\n if (isValueDynamicFilter(selectorConfig)) {\n if (selectorConfig.fallback) {\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n }\n\n const selectorType = isRowWithFieldDynamicFilter(selectorConfig) ? 'table' : 'chart'\n\n // 优先使用预先执行的结果\n if (selectorConfig.result?.success && selectorConfig.result.data) {\n return matchDynamicFilterResult(selectorConfig.result.data, vchartDatum, selectorType)\n }\n\n if (selectorConfig.fallback) {\n // 如果有 fallback,使用传统 selector 进行匹配\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n\n // 没有结果也没有 fallback,返回 false\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n}\n"],"names":["nearlyEqual","a","b","epsilon","Number","diff","Math","selector","vchartDatum","selectorMode","vchartKeys","Object","k","datum","omit","selectors","Array","isValueSelector","selectByValue","isFieldSelector","selectByField","isMeasureSelector","selectByMeasure","isDimensionSelector","selectByDmension","isPartialDatumSelector","selectByPartial","op","selectorValueArr","String","fields","datumKeys","field","matchesFieldSelector","fieldSelector","key","v","matchesCellSelector","cell","filterRes","InnerRowIndex","matchesDatum","target","candidate","isDynamicFilterLike","expectedTypes","isRowWithFieldDynamicFilter","isValueDynamicFilter","isDynamicFilter","validateFilterResult","result","filter","TypeError","i","item","executeDynamicFilter","allData","success","data","error","executeFilterCode","console","validationError","Error","errorMessage","matchDynamicFilterResult","selectorType","selectorWithDynamicFilter","selectorConfig","defaultSelector","fallbackSelector"],"mappings":"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"}
|
|
@@ -39,7 +39,7 @@ const barLoop = (config, ignoreFirstNormal, chartType, spec)=>{
|
|
|
39
39
|
if (loopEffect === VScreenAnimationType.highLight && loop) {
|
|
40
40
|
const groupDuration = 0.7;
|
|
41
41
|
const stopDuration = 0.85;
|
|
42
|
-
loopDuration = groupDuration * getGroupCountFromSpec(spec).groupCount + stopDuration;
|
|
42
|
+
loopDuration = loop.duration ?? groupDuration * getGroupCountFromSpec(spec).groupCount + stopDuration;
|
|
43
43
|
result.push(...groupHighLightBar(startTime, loop, loopDuration, interval, atmosphereDuration, isHorizontalBar(chartType), spec));
|
|
44
44
|
} else if (loop) result.push({
|
|
45
45
|
...getLoopResult(loopEffect, chartType, spec),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/chart/pipes/animation/bar.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/animation/bar.ts"],"sourcesContent":["import { StreamLight } from '@visactor/vchart'\nimport type { BarLikeAppearConfig, BarLikeLoopConfig, BarLikeUpdateConfig } from './types'\nimport { VScreenAnimationType } from './types'\nimport { allowAnimation, getPrimaryEffect, toMs } from './utils'\nimport {\n fadeInBar,\n getGroupCountFromSpec,\n getLoopResult,\n groupHighLightBar,\n growBar,\n isHorizontalBar,\n moveInBar,\n moveOutBar,\n transform2VChartColor,\n} from './utils/bar'\n\n/**\n * 柱图/条形图 入场动画\n * 动画类型:\n * 1. growth: 生长动画\n * 效果:横向柱使用宽度增长, 纵向柱使用高度增长。\n * 编排逻辑:仅作用于 bar mark, 使用 appear 的 easing 和 duration。\n * 2. load: 加载动画\n * 效果:使用逐个淡入, 让柱子按图元顺序出现。\n * 编排逻辑:仅作用于 bar mark, 使用 appear 的 easing 和 duration。\n * 3. 其他: 默认入场动画\n * 效果:不指定额外动画 type, 交给 VChart 默认入场补间。\n * 编排逻辑:仅保留 easing 和 duration。\n */\nexport const barAppear = (config: BarLikeAppearConfig | undefined, chartType: string) => {\n if (!allowAnimation(config)) return false\n const effect = getPrimaryEffect(config)\n const configByType =\n effect === VScreenAnimationType.growth\n ? growBar(chartType)\n : effect === VScreenAnimationType.load\n ? fadeInBar()\n : {}\n return { bar: { ...configByType, easing: config?.ease, duration: toMs(config?.duration ?? 1) } }\n}\n\n/**\n * 柱图/条形图 更新动画\n * 动画类型:\n * 1. moveIn: 移入动画\n * 效果:update 阶段沿柱图方向从画布外移入。\n * 编排逻辑:复用移入方向, 但不再补随机 dataKey, 只作用于 bar mark。\n * 2. 其他: 默认更新动画\n * 效果:使用 VChart 默认更新补间。\n * 编排逻辑:只保留 easing 和 duration, 不影响轴、标签等其他组件。\n */\nexport const barUpdate = (config: BarLikeUpdateConfig | undefined, chartType: string, spec?: any) => {\n if (!allowAnimation(config)) return false\n const effect = getPrimaryEffect(config)\n const configByType = effect === VScreenAnimationType.moveIn ? moveInBar(chartType, spec, true) : {}\n return { bar: { ...configByType, easing: config?.ease, duration: toMs(config?.duration ?? 1) } }\n}\n\n/**\n * 柱图/条形图 循环动画\n * 动画类型:\n * 1. highLight: 分组高亮动画\n * 效果:按类目分组依次切换高亮填充和描边。\n * 编排逻辑:startTime = appear 存在 ? interval : 0, loopDuration = groupDuration * groupCount + stopDuration, 一轮结束后等待 interval。\n * 2. growth/moveIn/load: mark 循环动画\n * 效果:复用对应的柱图 mark 动画。\n * 编排逻辑:先执行 loopDuration, 再等待 interval + atmosphereDuration 后重复。\n * 3. atmosphere: 流光氛围动画\n * 效果:使用 StreamLight 在柱子上形成流光。\n * 编排逻辑:延迟 loopDuration 后启动, 持续 atmosphereDuration, 一轮结束后等待 interval。\n */\nexport const barLoop = (\n config: BarLikeLoopConfig | undefined,\n ignoreFirstNormal: boolean,\n chartType: string,\n spec?: any,\n) => {\n if (!config?.enable) return false\n const interval = config.interval ?? 0\n const startTime = ignoreFirstNormal ? toMs(interval) : 0\n const loop = config.loop\n const atmosphere = config.atmosphere\n const loopEffect = getPrimaryEffect(loop)\n const result: any[] = []\n let loopDuration = loopEffect === VScreenAnimationType.none ? 0 : 1\n const atmosphereDuration = loopEffect === VScreenAnimationType.none ? 2 : 1\n\n if (loopEffect === VScreenAnimationType.highLight && loop) {\n const groupDuration = 0.7\n const stopDuration = 0.85\n loopDuration = groupDuration * getGroupCountFromSpec(spec).groupCount + stopDuration\n result.push(\n ...groupHighLightBar(\n startTime,\n loop,\n loopDuration,\n interval,\n atmosphereDuration,\n isHorizontalBar(chartType),\n spec,\n ),\n )\n } else if (loop) {\n result.push({\n ...getLoopResult(loopEffect, chartType, spec),\n startTime,\n easing: loop.ease,\n duration: toMs(loopDuration),\n delayAfter: toMs(interval + atmosphereDuration),\n loop: true,\n controlOptions: { immediatelyApply: false },\n })\n }\n\n if (atmosphere?.ease || atmosphere?.color) {\n result.push({\n loop: true,\n startTime,\n delay: toMs(loopDuration),\n delayAfter: toMs(interval),\n duration: toMs(atmosphereDuration),\n easing: atmosphere.ease,\n custom: StreamLight,\n customParameters: {\n isHorizontal: isHorizontalBar(chartType),\n attribute: {\n fill: transform2VChartColor(atmosphere.color),\n blur: 0,\n shadowColor: 'rgba(0,0,0,0)',\n },\n },\n })\n }\n\n return result.length > 0 ? { bar: result } : false\n}\n\n/**\n * 柱图/条形图 离场动画\n * 动画类型:\n * 1. moveIn: 反向移出动画\n * 效果:沿柱图进入方向反向移出画布。\n * 编排逻辑:只有 update 效果为 moveIn 时才补充 moveOut。\n * 2. 其他: 默认离场动画\n * 效果:不配置自定义 exit。\n * 编排逻辑:返回空配置, 由 VChart 默认行为处理。\n */\nexport const barExit = (config: BarLikeUpdateConfig | undefined, chartType: string) => {\n if (!allowAnimation(config)) return false\n if (getPrimaryEffect(config) !== VScreenAnimationType.moveIn) return {}\n return { bar: { ...moveOutBar(chartType), duration: 1000 } }\n}\n"],"names":["barAppear","config","chartType","allowAnimation","effect","getPrimaryEffect","configByType","VScreenAnimationType","growBar","fadeInBar","toMs","barUpdate","spec","moveInBar","barLoop","ignoreFirstNormal","interval","startTime","loop","atmosphere","loopEffect","result","loopDuration","atmosphereDuration","groupDuration","stopDuration","getGroupCountFromSpec","groupHighLightBar","isHorizontalBar","getLoopResult","StreamLight","transform2VChartColor","barExit","moveOutBar"],"mappings":";;;;AA6BO,MAAMA,YAAY,CAACC,QAAyCC;IACjE,IAAI,CAACC,eAAeF,SAAS,OAAO;IACpC,MAAMG,SAASC,iBAAiBJ;IAChC,MAAMK,eACJF,WAAWG,qBAAqB,MAAM,GAClCC,QAAQN,aACRE,WAAWG,qBAAqB,IAAI,GAClCE,cACA,CAAC;IACT,OAAO;QAAE,KAAK;YAAE,GAAGH,YAAY;YAAE,QAAQL,QAAQ;YAAM,UAAUS,KAAKT,QAAQ,YAAY;QAAG;IAAE;AACjG;AAYO,MAAMU,YAAY,CAACV,QAAyCC,WAAmBU;IACpF,IAAI,CAACT,eAAeF,SAAS,OAAO;IACpC,MAAMG,SAASC,iBAAiBJ;IAChC,MAAMK,eAAeF,WAAWG,qBAAqB,MAAM,GAAGM,UAAUX,WAAWU,MAAM,QAAQ,CAAC;IAClG,OAAO;QAAE,KAAK;YAAE,GAAGN,YAAY;YAAE,QAAQL,QAAQ;YAAM,UAAUS,KAAKT,QAAQ,YAAY;QAAG;IAAE;AACjG;AAeO,MAAMa,UAAU,CACrBb,QACAc,mBACAb,WACAU;IAEA,IAAI,CAACX,QAAQ,QAAQ,OAAO;IAC5B,MAAMe,WAAWf,OAAO,QAAQ,IAAI;IACpC,MAAMgB,YAAYF,oBAAoBL,KAAKM,YAAY;IACvD,MAAME,OAAOjB,OAAO,IAAI;IACxB,MAAMkB,aAAalB,OAAO,UAAU;IACpC,MAAMmB,aAAaf,iBAAiBa;IACpC,MAAMG,SAAgB,EAAE;IACxB,IAAIC,eAAeF,eAAeb,qBAAqB,IAAI,GAAG,IAAI;IAClE,MAAMgB,qBAAqBH,eAAeb,qBAAqB,IAAI,GAAG,IAAI;IAE1E,IAAIa,eAAeb,qBAAqB,SAAS,IAAIW,MAAM;QACzD,MAAMM,gBAAgB;QACtB,MAAMC,eAAe;QACrBH,
|
|
1
|
+
{"version":3,"file":"pipeline/spec/chart/pipes/animation/bar.js","sources":["../../../../../../../src/pipeline/spec/chart/pipes/animation/bar.ts"],"sourcesContent":["import { StreamLight } from '@visactor/vchart'\nimport type { BarLikeAppearConfig, BarLikeLoopConfig, BarLikeUpdateConfig } from './types'\nimport { VScreenAnimationType } from './types'\nimport { allowAnimation, getPrimaryEffect, toMs } from './utils'\nimport {\n fadeInBar,\n getGroupCountFromSpec,\n getLoopResult,\n groupHighLightBar,\n growBar,\n isHorizontalBar,\n moveInBar,\n moveOutBar,\n transform2VChartColor,\n} from './utils/bar'\n\n/**\n * 柱图/条形图 入场动画\n * 动画类型:\n * 1. growth: 生长动画\n * 效果:横向柱使用宽度增长, 纵向柱使用高度增长。\n * 编排逻辑:仅作用于 bar mark, 使用 appear 的 easing 和 duration。\n * 2. load: 加载动画\n * 效果:使用逐个淡入, 让柱子按图元顺序出现。\n * 编排逻辑:仅作用于 bar mark, 使用 appear 的 easing 和 duration。\n * 3. 其他: 默认入场动画\n * 效果:不指定额外动画 type, 交给 VChart 默认入场补间。\n * 编排逻辑:仅保留 easing 和 duration。\n */\nexport const barAppear = (config: BarLikeAppearConfig | undefined, chartType: string) => {\n if (!allowAnimation(config)) return false\n const effect = getPrimaryEffect(config)\n const configByType =\n effect === VScreenAnimationType.growth\n ? growBar(chartType)\n : effect === VScreenAnimationType.load\n ? fadeInBar()\n : {}\n return { bar: { ...configByType, easing: config?.ease, duration: toMs(config?.duration ?? 1) } }\n}\n\n/**\n * 柱图/条形图 更新动画\n * 动画类型:\n * 1. moveIn: 移入动画\n * 效果:update 阶段沿柱图方向从画布外移入。\n * 编排逻辑:复用移入方向, 但不再补随机 dataKey, 只作用于 bar mark。\n * 2. 其他: 默认更新动画\n * 效果:使用 VChart 默认更新补间。\n * 编排逻辑:只保留 easing 和 duration, 不影响轴、标签等其他组件。\n */\nexport const barUpdate = (config: BarLikeUpdateConfig | undefined, chartType: string, spec?: any) => {\n if (!allowAnimation(config)) return false\n const effect = getPrimaryEffect(config)\n const configByType = effect === VScreenAnimationType.moveIn ? moveInBar(chartType, spec, true) : {}\n return { bar: { ...configByType, easing: config?.ease, duration: toMs(config?.duration ?? 1) } }\n}\n\n/**\n * 柱图/条形图 循环动画\n * 动画类型:\n * 1. highLight: 分组高亮动画\n * 效果:按类目分组依次切换高亮填充和描边。\n * 编排逻辑:startTime = appear 存在 ? interval : 0, loopDuration = groupDuration * groupCount + stopDuration, 一轮结束后等待 interval。\n * 2. growth/moveIn/load: mark 循环动画\n * 效果:复用对应的柱图 mark 动画。\n * 编排逻辑:先执行 loopDuration, 再等待 interval + atmosphereDuration 后重复。\n * 3. atmosphere: 流光氛围动画\n * 效果:使用 StreamLight 在柱子上形成流光。\n * 编排逻辑:延迟 loopDuration 后启动, 持续 atmosphereDuration, 一轮结束后等待 interval。\n */\nexport const barLoop = (\n config: BarLikeLoopConfig | undefined,\n ignoreFirstNormal: boolean,\n chartType: string,\n spec?: any,\n) => {\n if (!config?.enable) return false\n const interval = config.interval ?? 0\n const startTime = ignoreFirstNormal ? toMs(interval) : 0\n const loop = config.loop\n const atmosphere = config.atmosphere\n const loopEffect = getPrimaryEffect(loop)\n const result: any[] = []\n let loopDuration = loopEffect === VScreenAnimationType.none ? 0 : 1\n const atmosphereDuration = loopEffect === VScreenAnimationType.none ? 2 : 1\n\n if (loopEffect === VScreenAnimationType.highLight && loop) {\n const groupDuration = 0.7\n const stopDuration = 0.85\n loopDuration = loop.duration ?? groupDuration * getGroupCountFromSpec(spec).groupCount + stopDuration\n result.push(\n ...groupHighLightBar(\n startTime,\n loop,\n loopDuration,\n interval,\n atmosphereDuration,\n isHorizontalBar(chartType),\n spec,\n ),\n )\n } else if (loop) {\n result.push({\n ...getLoopResult(loopEffect, chartType, spec),\n startTime,\n easing: loop.ease,\n duration: toMs(loopDuration),\n delayAfter: toMs(interval + atmosphereDuration),\n loop: true,\n controlOptions: { immediatelyApply: false },\n })\n }\n\n if (atmosphere?.ease || atmosphere?.color) {\n result.push({\n loop: true,\n startTime,\n delay: toMs(loopDuration),\n delayAfter: toMs(interval),\n duration: toMs(atmosphereDuration),\n easing: atmosphere.ease,\n custom: StreamLight,\n customParameters: {\n isHorizontal: isHorizontalBar(chartType),\n attribute: {\n fill: transform2VChartColor(atmosphere.color),\n blur: 0,\n shadowColor: 'rgba(0,0,0,0)',\n },\n },\n })\n }\n\n return result.length > 0 ? { bar: result } : false\n}\n\n/**\n * 柱图/条形图 离场动画\n * 动画类型:\n * 1. moveIn: 反向移出动画\n * 效果:沿柱图进入方向反向移出画布。\n * 编排逻辑:只有 update 效果为 moveIn 时才补充 moveOut。\n * 2. 其他: 默认离场动画\n * 效果:不配置自定义 exit。\n * 编排逻辑:返回空配置, 由 VChart 默认行为处理。\n */\nexport const barExit = (config: BarLikeUpdateConfig | undefined, chartType: string) => {\n if (!allowAnimation(config)) return false\n if (getPrimaryEffect(config) !== VScreenAnimationType.moveIn) return {}\n return { bar: { ...moveOutBar(chartType), duration: 1000 } }\n}\n"],"names":["barAppear","config","chartType","allowAnimation","effect","getPrimaryEffect","configByType","VScreenAnimationType","growBar","fadeInBar","toMs","barUpdate","spec","moveInBar","barLoop","ignoreFirstNormal","interval","startTime","loop","atmosphere","loopEffect","result","loopDuration","atmosphereDuration","groupDuration","stopDuration","getGroupCountFromSpec","groupHighLightBar","isHorizontalBar","getLoopResult","StreamLight","transform2VChartColor","barExit","moveOutBar"],"mappings":";;;;AA6BO,MAAMA,YAAY,CAACC,QAAyCC;IACjE,IAAI,CAACC,eAAeF,SAAS,OAAO;IACpC,MAAMG,SAASC,iBAAiBJ;IAChC,MAAMK,eACJF,WAAWG,qBAAqB,MAAM,GAClCC,QAAQN,aACRE,WAAWG,qBAAqB,IAAI,GAClCE,cACA,CAAC;IACT,OAAO;QAAE,KAAK;YAAE,GAAGH,YAAY;YAAE,QAAQL,QAAQ;YAAM,UAAUS,KAAKT,QAAQ,YAAY;QAAG;IAAE;AACjG;AAYO,MAAMU,YAAY,CAACV,QAAyCC,WAAmBU;IACpF,IAAI,CAACT,eAAeF,SAAS,OAAO;IACpC,MAAMG,SAASC,iBAAiBJ;IAChC,MAAMK,eAAeF,WAAWG,qBAAqB,MAAM,GAAGM,UAAUX,WAAWU,MAAM,QAAQ,CAAC;IAClG,OAAO;QAAE,KAAK;YAAE,GAAGN,YAAY;YAAE,QAAQL,QAAQ;YAAM,UAAUS,KAAKT,QAAQ,YAAY;QAAG;IAAE;AACjG;AAeO,MAAMa,UAAU,CACrBb,QACAc,mBACAb,WACAU;IAEA,IAAI,CAACX,QAAQ,QAAQ,OAAO;IAC5B,MAAMe,WAAWf,OAAO,QAAQ,IAAI;IACpC,MAAMgB,YAAYF,oBAAoBL,KAAKM,YAAY;IACvD,MAAME,OAAOjB,OAAO,IAAI;IACxB,MAAMkB,aAAalB,OAAO,UAAU;IACpC,MAAMmB,aAAaf,iBAAiBa;IACpC,MAAMG,SAAgB,EAAE;IACxB,IAAIC,eAAeF,eAAeb,qBAAqB,IAAI,GAAG,IAAI;IAClE,MAAMgB,qBAAqBH,eAAeb,qBAAqB,IAAI,GAAG,IAAI;IAE1E,IAAIa,eAAeb,qBAAqB,SAAS,IAAIW,MAAM;QACzD,MAAMM,gBAAgB;QACtB,MAAMC,eAAe;QACrBH,eAAeJ,KAAK,QAAQ,IAAIM,gBAAgBE,sBAAsBd,MAAM,UAAU,GAAGa;QACzFJ,OAAO,IAAI,IACNM,kBACDV,WACAC,MACAI,cACAN,UACAO,oBACAK,gBAAgB1B,YAChBU;IAGN,OAAO,IAAIM,MACTG,OAAO,IAAI,CAAC;QACV,GAAGQ,cAAcT,YAAYlB,WAAWU,KAAK;QAC7CK;QACA,QAAQC,KAAK,IAAI;QACjB,UAAUR,KAAKY;QACf,YAAYZ,KAAKM,WAAWO;QAC5B,MAAM;QACN,gBAAgB;YAAE,kBAAkB;QAAM;IAC5C;IAGF,IAAIJ,YAAY,QAAQA,YAAY,OAClCE,OAAO,IAAI,CAAC;QACV,MAAM;QACNJ;QACA,OAAOP,KAAKY;QACZ,YAAYZ,KAAKM;QACjB,UAAUN,KAAKa;QACf,QAAQJ,WAAW,IAAI;QACvB,QAAQW;QACR,kBAAkB;YAChB,cAAcF,gBAAgB1B;YAC9B,WAAW;gBACT,MAAM6B,sBAAsBZ,WAAW,KAAK;gBAC5C,MAAM;gBACN,aAAa;YACf;QACF;IACF;IAGF,OAAOE,OAAO,MAAM,GAAG,IAAI;QAAE,KAAKA;IAAO,IAAI;AAC/C;AAYO,MAAMW,UAAU,CAAC/B,QAAyCC;IAC/D,IAAI,CAACC,eAAeF,SAAS,OAAO;IACpC,IAAII,iBAAiBJ,YAAYM,qBAAqB,MAAM,EAAE,OAAO,CAAC;IACtE,OAAO;QAAE,KAAK;YAAE,GAAG0B,WAAW/B,UAAU;YAAE,UAAU;QAAK;IAAE;AAC7D"}
|
|
@@ -142,6 +142,7 @@ export declare const lineOrAreaLoop: (config: LineAreaLoopConfig | undefined, ig
|
|
|
142
142
|
})[];
|
|
143
143
|
point: ({
|
|
144
144
|
channel?: undefined;
|
|
145
|
+
custom?: undefined;
|
|
145
146
|
loop: boolean;
|
|
146
147
|
startTime: number;
|
|
147
148
|
delayAfter: number;
|
|
@@ -161,6 +162,7 @@ export declare const lineOrAreaLoop: (config: LineAreaLoopConfig | undefined, ig
|
|
|
161
162
|
strokeOpacity?: undefined;
|
|
162
163
|
outerBorder?: undefined;
|
|
163
164
|
};
|
|
165
|
+
custom?: undefined;
|
|
164
166
|
loop: boolean;
|
|
165
167
|
startTime: number;
|
|
166
168
|
delayAfter: number;
|
|
@@ -180,6 +182,7 @@ export declare const lineOrAreaLoop: (config: LineAreaLoopConfig | undefined, ig
|
|
|
180
182
|
scaleY?: undefined;
|
|
181
183
|
outerBorder?: undefined;
|
|
182
184
|
};
|
|
185
|
+
custom?: undefined;
|
|
183
186
|
loop: boolean;
|
|
184
187
|
startTime: number;
|
|
185
188
|
delayAfter: number;
|
|
@@ -203,6 +206,7 @@ export declare const lineOrAreaLoop: (config: LineAreaLoopConfig | undefined, ig
|
|
|
203
206
|
fillOpacity?: undefined;
|
|
204
207
|
strokeOpacity?: undefined;
|
|
205
208
|
};
|
|
209
|
+
custom: (ratio: number, from: any, to: any, out: any, graphic: any) => void;
|
|
206
210
|
loop: boolean;
|
|
207
211
|
startTime: number;
|
|
208
212
|
delayAfter: number;
|
|
@@ -30,6 +30,7 @@ export declare const radarLoop: (config: RadarLoopConfig | undefined, ignoreFirs
|
|
|
30
30
|
immediatelyApply: boolean;
|
|
31
31
|
};
|
|
32
32
|
channel?: undefined;
|
|
33
|
+
custom?: undefined;
|
|
33
34
|
loop: boolean;
|
|
34
35
|
startTime: number;
|
|
35
36
|
delayAfter: number;
|
|
@@ -52,6 +53,7 @@ export declare const radarLoop: (config: RadarLoopConfig | undefined, ignoreFirs
|
|
|
52
53
|
strokeOpacity?: undefined;
|
|
53
54
|
outerBorder?: undefined;
|
|
54
55
|
};
|
|
56
|
+
custom?: undefined;
|
|
55
57
|
loop: boolean;
|
|
56
58
|
startTime: number;
|
|
57
59
|
delayAfter: number;
|
|
@@ -74,6 +76,7 @@ export declare const radarLoop: (config: RadarLoopConfig | undefined, ignoreFirs
|
|
|
74
76
|
scaleY?: undefined;
|
|
75
77
|
outerBorder?: undefined;
|
|
76
78
|
};
|
|
79
|
+
custom?: undefined;
|
|
77
80
|
loop: boolean;
|
|
78
81
|
startTime: number;
|
|
79
82
|
delayAfter: number;
|
|
@@ -100,6 +103,7 @@ export declare const radarLoop: (config: RadarLoopConfig | undefined, ignoreFirs
|
|
|
100
103
|
fillOpacity?: undefined;
|
|
101
104
|
strokeOpacity?: undefined;
|
|
102
105
|
};
|
|
106
|
+
custom: (ratio: number, from: any, to: any, out: any, graphic: any) => void;
|
|
103
107
|
loop: boolean;
|
|
104
108
|
startTime: number;
|
|
105
109
|
delayAfter: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AnimationEffect, type AnimationEffectConfig } from '../types';
|
|
2
|
+
export { atmospherePoint, getFinalAttribute } from './pointAtmosphere';
|
|
2
3
|
export declare const EFFECT_NONE: "none";
|
|
3
4
|
/**
|
|
4
5
|
* @description 将秒转换为 VChart 动画使用的毫秒。
|
|
@@ -24,63 +25,3 @@ export declare const allowAnimation: (config?: AnimationEffectConfig) => boolean
|
|
|
24
25
|
* @returns 是否允许执行折线/面积动画。
|
|
25
26
|
*/
|
|
26
27
|
export declare const allowLineOrAreaAnimation: (config?: AnimationEffectConfig) => boolean;
|
|
27
|
-
/**
|
|
28
|
-
* @description 获取图元最终属性,优先读取动画后的 finalAttribute。
|
|
29
|
-
* @param mark VChart 图元对象。
|
|
30
|
-
* @returns 图元最终属性。
|
|
31
|
-
*/
|
|
32
|
-
export declare const getFinalAttribute: (mark: any) => Record<string, any>;
|
|
33
|
-
/**
|
|
34
|
-
* @description 生成点图元氛围动画配置,复用于折线、面积、散点和雷达图。
|
|
35
|
-
* @param effect 氛围动画效果。
|
|
36
|
-
* @returns 点图元氛围动画配置。
|
|
37
|
-
*/
|
|
38
|
-
export declare const atmospherePoint: (effect?: AnimationEffect) => {
|
|
39
|
-
channel?: undefined;
|
|
40
|
-
} | {
|
|
41
|
-
channel: {
|
|
42
|
-
scaleX: {
|
|
43
|
-
from: number;
|
|
44
|
-
to: number;
|
|
45
|
-
};
|
|
46
|
-
scaleY: {
|
|
47
|
-
from: number;
|
|
48
|
-
to: number;
|
|
49
|
-
};
|
|
50
|
-
fillOpacity?: undefined;
|
|
51
|
-
strokeOpacity?: undefined;
|
|
52
|
-
outerBorder?: undefined;
|
|
53
|
-
};
|
|
54
|
-
} | {
|
|
55
|
-
channel: {
|
|
56
|
-
fillOpacity: {
|
|
57
|
-
from: number;
|
|
58
|
-
to: number;
|
|
59
|
-
};
|
|
60
|
-
strokeOpacity: {
|
|
61
|
-
from: number;
|
|
62
|
-
to: number;
|
|
63
|
-
};
|
|
64
|
-
scaleX?: undefined;
|
|
65
|
-
scaleY?: undefined;
|
|
66
|
-
outerBorder?: undefined;
|
|
67
|
-
};
|
|
68
|
-
} | {
|
|
69
|
-
channel: {
|
|
70
|
-
outerBorder: {
|
|
71
|
-
from: {
|
|
72
|
-
distance: number;
|
|
73
|
-
strokeOpacity: number;
|
|
74
|
-
};
|
|
75
|
-
to: (...args: any[]) => {
|
|
76
|
-
distance: number;
|
|
77
|
-
strokeOpacity: number;
|
|
78
|
-
stroke: any;
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
scaleX?: undefined;
|
|
82
|
-
scaleY?: undefined;
|
|
83
|
-
fillOpacity?: undefined;
|
|
84
|
-
strokeOpacity?: undefined;
|
|
85
|
-
};
|
|
86
|
-
};
|
|
@@ -12,49 +12,7 @@ const allowLineOrAreaAnimation = (config)=>{
|
|
|
12
12
|
const effect = effects[effects.length - 1] ?? EFFECT_NONE;
|
|
13
13
|
return effect !== EFFECT_NONE;
|
|
14
14
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (effect === EFFECT_NONE) return {};
|
|
18
|
-
if ('breath' === effect) return {
|
|
19
|
-
channel: {
|
|
20
|
-
scaleX: {
|
|
21
|
-
from: 0.8,
|
|
22
|
-
to: 1.2
|
|
23
|
-
},
|
|
24
|
-
scaleY: {
|
|
25
|
-
from: 0.8,
|
|
26
|
-
to: 1.2
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
if ('reveal' === effect) return {
|
|
31
|
-
channel: {
|
|
32
|
-
fillOpacity: {
|
|
33
|
-
from: 0.6,
|
|
34
|
-
to: 1
|
|
35
|
-
},
|
|
36
|
-
strokeOpacity: {
|
|
37
|
-
from: 0.6,
|
|
38
|
-
to: 1
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
return {
|
|
43
|
-
channel: {
|
|
44
|
-
outerBorder: {
|
|
45
|
-
from: {
|
|
46
|
-
distance: 0,
|
|
47
|
-
strokeOpacity: 1
|
|
48
|
-
},
|
|
49
|
-
to: (...args)=>({
|
|
50
|
-
distance: 16,
|
|
51
|
-
strokeOpacity: 1e-8,
|
|
52
|
-
stroke: args[1]?.attribute?.fill
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
export { EFFECT_NONE, allowAnimation, allowLineOrAreaAnimation, atmospherePoint, getFinalAttribute, getPrimaryEffect, toMs };
|
|
15
|
+
export { atmospherePoint, getFinalAttribute } from "./pointAtmosphere.js";
|
|
16
|
+
export { EFFECT_NONE, allowAnimation, allowLineOrAreaAnimation, getPrimaryEffect, toMs };
|
|
59
17
|
|
|
60
18
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/chart/pipes/animation/utils/index.js","sources":["../../../../../../../../src/pipeline/spec/chart/pipes/animation/utils/index.ts"],"sourcesContent":["import { VScreenAnimationType, type AnimationEffect, type AnimationEffectConfig } from '../types'\n\nexport const EFFECT_NONE = VScreenAnimationType.none\n\n/**\n * @description 将秒转换为 VChart 动画使用的毫秒。\n * @param seconds 秒数。\n * @returns 毫秒数。\n */\nexport const toMs = (seconds?: number): number => (seconds ?? 0) * 1000\n\n/**\n * @description 获取配置中的首个动画效果;未配置时返回 none。\n * @param config 动画效果配置。\n * @returns 首个动画效果。\n */\nexport const getPrimaryEffect = (config?: AnimationEffectConfig): AnimationEffect => config?.effects?.[0] ?? EFFECT_NONE\n\n/**\n * @description 判断通用动画配置是否开启且首个效果不是 none。\n * @param config 动画效果配置。\n * @returns 是否允许执行动画。\n */\nexport const allowAnimation = (config?: AnimationEffectConfig): boolean => {\n if (!config?.enable) {\n return false\n }\n return getPrimaryEffect(config) !== EFFECT_NONE\n}\n\n/**\n * @description 判断折线/面积动画是否开启;这类图表以最后一个效果作为有效性判断。\n * @param config 动画效果配置。\n * @returns 是否允许执行折线/面积动画。\n */\nexport const allowLineOrAreaAnimation = (config?: AnimationEffectConfig): boolean => {\n if (!config?.enable) {\n return false\n }\n const effects = config.effects ?? []\n const effect = effects[effects.length - 1] ?? EFFECT_NONE\n return effect !== EFFECT_NONE\n}\n
|
|
1
|
+
{"version":3,"file":"pipeline/spec/chart/pipes/animation/utils/index.js","sources":["../../../../../../../../src/pipeline/spec/chart/pipes/animation/utils/index.ts"],"sourcesContent":["import { VScreenAnimationType, type AnimationEffect, type AnimationEffectConfig } from '../types'\nexport { atmospherePoint, getFinalAttribute } from './pointAtmosphere'\n\nexport const EFFECT_NONE = VScreenAnimationType.none\n\n/**\n * @description 将秒转换为 VChart 动画使用的毫秒。\n * @param seconds 秒数。\n * @returns 毫秒数。\n */\nexport const toMs = (seconds?: number): number => (seconds ?? 0) * 1000\n\n/**\n * @description 获取配置中的首个动画效果;未配置时返回 none。\n * @param config 动画效果配置。\n * @returns 首个动画效果。\n */\nexport const getPrimaryEffect = (config?: AnimationEffectConfig): AnimationEffect => config?.effects?.[0] ?? EFFECT_NONE\n\n/**\n * @description 判断通用动画配置是否开启且首个效果不是 none。\n * @param config 动画效果配置。\n * @returns 是否允许执行动画。\n */\nexport const allowAnimation = (config?: AnimationEffectConfig): boolean => {\n if (!config?.enable) {\n return false\n }\n return getPrimaryEffect(config) !== EFFECT_NONE\n}\n\n/**\n * @description 判断折线/面积动画是否开启;这类图表以最后一个效果作为有效性判断。\n * @param config 动画效果配置。\n * @returns 是否允许执行折线/面积动画。\n */\nexport const allowLineOrAreaAnimation = (config?: AnimationEffectConfig): boolean => {\n if (!config?.enable) {\n return false\n }\n const effects = config.effects ?? []\n const effect = effects[effects.length - 1] ?? EFFECT_NONE\n return effect !== EFFECT_NONE\n}\n"],"names":["EFFECT_NONE","VScreenAnimationType","toMs","seconds","getPrimaryEffect","config","allowAnimation","allowLineOrAreaAnimation","effects","effect"],"mappings":";AAGO,MAAMA,cAAcC,qBAAqB,IAAI;AAO7C,MAAMC,OAAO,CAACC,UAA8BA,AAAAA,CAAAA,WAAW,KAAK;AAO5D,MAAMC,mBAAmB,CAACC,SAAoDA,QAAQ,SAAS,CAAC,EAAE,IAAIL;AAOtG,MAAMM,iBAAiB,CAACD;IAC7B,IAAI,CAACA,QAAQ,QACX,OAAO;IAET,OAAOD,iBAAiBC,YAAYL;AACtC;AAOO,MAAMO,2BAA2B,CAACF;IACvC,IAAI,CAACA,QAAQ,QACX,OAAO;IAET,MAAMG,UAAUH,OAAO,OAAO,IAAI,EAAE;IACpC,MAAMI,SAASD,OAAO,CAACA,QAAQ,MAAM,GAAG,EAAE,IAAIR;IAC9C,OAAOS,WAAWT;AACpB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type AnimationEffect } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description 获取图元最终属性,优先读取动画后的 finalAttribute。
|
|
4
|
+
* @param mark VChart 图元对象。
|
|
5
|
+
* @returns 图元最终属性。
|
|
6
|
+
*/
|
|
7
|
+
export declare const getFinalAttribute: (mark: any) => Record<string, any>;
|
|
8
|
+
/**
|
|
9
|
+
* @description 生成点图元氛围动画配置,复用于折线、面积、散点和雷达图。
|
|
10
|
+
* @param effect 氛围动画效果。
|
|
11
|
+
* @returns 点图元氛围动画配置。
|
|
12
|
+
*/
|
|
13
|
+
export declare const atmospherePoint: (effect?: AnimationEffect) => {
|
|
14
|
+
channel?: undefined;
|
|
15
|
+
custom?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
channel: {
|
|
18
|
+
scaleX: {
|
|
19
|
+
from: number;
|
|
20
|
+
to: number;
|
|
21
|
+
};
|
|
22
|
+
scaleY: {
|
|
23
|
+
from: number;
|
|
24
|
+
to: number;
|
|
25
|
+
};
|
|
26
|
+
fillOpacity?: undefined;
|
|
27
|
+
strokeOpacity?: undefined;
|
|
28
|
+
outerBorder?: undefined;
|
|
29
|
+
};
|
|
30
|
+
custom?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
channel: {
|
|
33
|
+
fillOpacity: {
|
|
34
|
+
from: number;
|
|
35
|
+
to: number;
|
|
36
|
+
};
|
|
37
|
+
strokeOpacity: {
|
|
38
|
+
from: number;
|
|
39
|
+
to: number;
|
|
40
|
+
};
|
|
41
|
+
scaleX?: undefined;
|
|
42
|
+
scaleY?: undefined;
|
|
43
|
+
outerBorder?: undefined;
|
|
44
|
+
};
|
|
45
|
+
custom?: undefined;
|
|
46
|
+
} | {
|
|
47
|
+
channel: {
|
|
48
|
+
outerBorder: {
|
|
49
|
+
from: {
|
|
50
|
+
distance: number;
|
|
51
|
+
strokeOpacity: number;
|
|
52
|
+
};
|
|
53
|
+
to: (...args: any[]) => {
|
|
54
|
+
distance: number;
|
|
55
|
+
strokeOpacity: number;
|
|
56
|
+
stroke: any;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
scaleX?: undefined;
|
|
60
|
+
scaleY?: undefined;
|
|
61
|
+
fillOpacity?: undefined;
|
|
62
|
+
strokeOpacity?: undefined;
|
|
63
|
+
};
|
|
64
|
+
custom: (ratio: number, from: any, to: any, out: any, graphic: any) => void;
|
|
65
|
+
};
|