@zerodep-dev/vue-tsx-pro-ui 0.3.3 → 0.4.1
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/charts/AreaChart.d.ts +1 -1
- package/dist/charts/AreaChart.js +6 -48
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.js +6 -49
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/ChordChart.d.ts +7 -2
- package/dist/charts/ChordChart.js +151 -60
- package/dist/charts/ChordChart.js.map +1 -1
- package/dist/charts/ComboChart.d.ts +2 -1
- package/dist/charts/ComboChart.js +17 -93
- package/dist/charts/ComboChart.js.map +1 -1
- package/dist/charts/DonutChart.d.ts +6 -1
- package/dist/charts/DonutChart.js +134 -51
- package/dist/charts/DonutChart.js.map +1 -1
- package/dist/charts/FunnelChart.js.map +1 -1
- package/dist/charts/GraphChart.d.ts +22 -10
- package/dist/charts/GraphChart.js +415 -175
- package/dist/charts/GraphChart.js.map +1 -1
- package/dist/charts/LineChart.d.ts +1 -29
- package/dist/charts/LineChart.js +6 -54
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/MapChart.d.ts +21 -48
- package/dist/charts/MapChart.js +426 -353
- package/dist/charts/MapChart.js.map +1 -1
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/SankeyChart.d.ts +7 -2
- package/dist/charts/SankeyChart.js +164 -76
- package/dist/charts/SankeyChart.js.map +1 -1
- package/dist/charts/ScatterChart.d.ts +7 -1
- package/dist/charts/ScatterChart.js +45 -30
- package/dist/charts/ScatterChart.js.map +1 -1
- package/dist/charts/TimelineChart.d.ts +8 -1
- package/dist/charts/TimelineChart.js +141 -89
- package/dist/charts/TimelineChart.js.map +1 -1
- package/dist/charts/TreemapChart.d.ts +6 -0
- package/dist/charts/TreemapChart.js +174 -58
- package/dist/charts/TreemapChart.js.map +1 -1
- package/dist/charts/WaterfallChart.d.ts +6 -7
- package/dist/charts/WaterfallChart.js +46 -51
- package/dist/charts/WaterfallChart.js.map +1 -1
- package/dist/charts/XYChart.d.ts +44 -35
- package/dist/charts/XYChart.js +493 -281
- package/dist/charts/XYChart.js.map +1 -1
- package/dist/charts/axis-ticks.d.ts +1 -1
- package/dist/charts/axis-ticks.js +4 -5
- package/dist/charts/axis-ticks.js.map +1 -1
- package/dist/charts/flow.d.ts +4 -11
- package/dist/charts/flow.js +4 -4
- package/dist/charts/flow.js.map +1 -1
- package/dist/charts/frame.d.ts +6 -30
- package/dist/charts/frame.js +6 -99
- package/dist/charts/frame.js.map +1 -1
- package/dist/charts/geo/projection.d.ts +45 -0
- package/dist/charts/geo/projection.js +201 -0
- package/dist/charts/geo/projection.js.map +1 -0
- package/dist/charts/geo/topojson.d.ts +50 -0
- package/dist/charts/geo/topojson.js +119 -0
- package/dist/charts/geo/topojson.js.map +1 -0
- package/dist/charts/index.d.ts +21 -9
- package/dist/charts/index.js +19 -8
- package/dist/charts/label-layout.js.map +1 -1
- package/dist/charts/layout/chord.d.ts +44 -0
- package/dist/charts/layout/chord.js +45 -0
- package/dist/charts/layout/chord.js.map +1 -0
- package/dist/charts/layout/graph.d.ts +49 -0
- package/dist/charts/layout/graph.js +268 -0
- package/dist/charts/layout/graph.js.map +1 -0
- package/dist/charts/layout/sankey.d.ts +79 -0
- package/dist/charts/layout/sankey.js +200 -0
- package/dist/charts/layout/sankey.js.map +1 -0
- package/dist/charts/layout/treemap.d.ts +46 -0
- package/dist/charts/layout/treemap.js +152 -0
- package/dist/charts/layout/treemap.js.map +1 -0
- package/dist/charts/marks.d.ts +79 -0
- package/dist/charts/marks.js +231 -0
- package/dist/charts/marks.js.map +1 -0
- package/dist/charts/plot.d.ts +107 -0
- package/dist/charts/plot.js +231 -0
- package/dist/charts/plot.js.map +1 -0
- package/dist/charts/scale.d.ts +29 -0
- package/dist/charts/scale.js +244 -0
- package/dist/charts/scale.js.map +1 -0
- package/dist/charts/shape.d.ts +46 -0
- package/dist/charts/shape.js +131 -0
- package/dist/charts/shape.js.map +1 -0
- package/dist/charts/stack.d.ts +17 -0
- package/dist/charts/stack.js +35 -0
- package/dist/charts/stack.js.map +1 -0
- package/dist/charts/text-size.d.ts +12 -0
- package/dist/charts/text-size.js +32 -0
- package/dist/charts/text-size.js.map +1 -0
- package/dist/config/createUi.d.ts +21 -2
- package/dist/config/createUi.js +18 -1
- package/dist/config/createUi.js.map +1 -1
- package/dist/config/theme/preference.js +2 -1
- package/dist/config/theme/preference.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/maps/china-provinces.js +35680 -0
- package/dist/maps/china-provinces.js.map +1 -0
- package/dist/maps/china.d.ts +13 -0
- package/dist/maps/china.js +8 -0
- package/dist/maps/china.js.map +1 -0
- package/dist/maps/index.d.ts +9 -0
- package/dist/maps/index.js +3 -0
- package/dist/maps/world-countries.js +22273 -0
- package/dist/maps/world-countries.js.map +1 -0
- package/dist/maps/world.d.ts +13 -0
- package/dist/maps/world.js +8 -0
- package/dist/maps/world.js.map +1 -0
- package/dist/overlay/detached.js.map +1 -1
- package/dist/utils/request/use-request.d.ts +25 -1
- package/dist/utils/request/use-request.js +35 -3
- package/dist/utils/request/use-request.js.map +1 -1
- package/package.json +7 -8
- package/dist/charts/single.d.ts +0 -41
- package/dist/charts/single.js +0 -66
- package/dist/charts/single.js.map +0 -1
package/dist/charts/AreaChart.js
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
|
+
import { chartAreas } from "./marks.js";
|
|
1
2
|
import { XYChart } from "./XYChart.js";
|
|
2
|
-
import { CURVES } from "./LineChart.js";
|
|
3
3
|
import { computed, createVNode } from "vue";
|
|
4
4
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
5
|
-
import { Area } from "@unovis/ts";
|
|
6
5
|
//#region src/charts/AreaChart.tsx
|
|
7
|
-
/**
|
|
8
|
-
* 面积图:每个系列一片面积,上沿描一条线;默认各系列重叠、半透明(看得出谁高谁低),stacked 时依次叠起(看总量与构成),
|
|
9
|
-
* stacked="percent" 时按占比叠满 100%(只看构成的变化)。
|
|
10
|
-
*
|
|
11
|
-
* <AreaChart data={months} index="month" series={[{ key: 'visits', label: '访问量' }]} />
|
|
12
|
-
* <AreaChart stacked data={months} index="month" series={channels} unit="万次" />
|
|
13
|
-
* <AreaChart stacked="percent" data={months} index="month" series={channels} />
|
|
14
|
-
*
|
|
15
|
-
* 坐标轴、十字线(带圆点)与提示框、图例、单位、加载与空状态、给读屏的数据表同 LineChart(见 XYChart)。
|
|
16
|
-
*/
|
|
17
6
|
/** 未声明的属性落到外层 div(role="figure")上 */
|
|
18
7
|
/** 面积图 */
|
|
19
8
|
var AreaChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
@@ -32,42 +21,11 @@ var AreaChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
32
21
|
right: 12,
|
|
33
22
|
top: 8
|
|
34
23
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
lineWidth: 2
|
|
41
|
-
};
|
|
42
|
-
if (stacked.value) {
|
|
43
|
-
const area = instance("stacked", () => new Area({
|
|
44
|
-
x,
|
|
45
|
-
y: []
|
|
46
|
-
}));
|
|
47
|
-
area.setConfig({
|
|
48
|
-
...common,
|
|
49
|
-
y: series.map(y),
|
|
50
|
-
color: (_rows, position) => series[position]?.color,
|
|
51
|
-
lineColor: (_rows, position) => series[position]?.color,
|
|
52
|
-
opacity: opacity.value ?? .8
|
|
53
|
-
});
|
|
54
|
-
return [area];
|
|
55
|
-
}
|
|
56
|
-
return series.map((item) => {
|
|
57
|
-
const area = instance(`area:${item.key}`, () => new Area({
|
|
58
|
-
x,
|
|
59
|
-
y: () => 0
|
|
60
|
-
}));
|
|
61
|
-
area.setConfig({
|
|
62
|
-
...common,
|
|
63
|
-
y: y(item),
|
|
64
|
-
color: item.color,
|
|
65
|
-
lineColor: item.color,
|
|
66
|
-
opacity: opacity.value ?? .25
|
|
67
|
-
});
|
|
68
|
-
return area;
|
|
69
|
-
});
|
|
70
|
-
}
|
|
24
|
+
render: (context) => chartAreas(context, context.series, {
|
|
25
|
+
curve: curve.value,
|
|
26
|
+
stacked: stacked.value !== false,
|
|
27
|
+
opacity: opacity.value ?? (stacked.value ? .8 : .25)
|
|
28
|
+
})
|
|
71
29
|
}));
|
|
72
30
|
return () => createVNode(XYChart, mergeJsxProps(rest, {
|
|
73
31
|
"_hiddenSeries": hiddenSeries.value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AreaChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/charts/AreaChart.tsx"],"sourcesContent":["/**\n * 面积图:每个系列一片面积,上沿描一条线;默认各系列重叠、半透明(看得出谁高谁低),stacked 时依次叠起(看总量与构成),\n * stacked=\"percent\" 时按占比叠满 100%(只看构成的变化)。\n *\n * <AreaChart data={months} index=\"month\" series={[{ key: 'visits', label: '访问量' }]} />\n * <AreaChart stacked data={months} index=\"month\" series={channels} unit=\"万次\" />\n * <AreaChart stacked=\"percent\" data={months} index=\"month\" series={channels} />\n *\n * 坐标轴、十字线(带圆点)与提示框、图例、单位、加载与空状态、给读屏的数据表同 LineChart(见 XYChart)。\n */\nimport {
|
|
1
|
+
{"version":3,"file":"AreaChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/charts/AreaChart.tsx"],"sourcesContent":["/**\n * 面积图:每个系列一片面积,上沿描一条线;默认各系列重叠、半透明(看得出谁高谁低),stacked 时依次叠起(看总量与构成),\n * stacked=\"percent\" 时按占比叠满 100%(只看构成的变化)。\n *\n * <AreaChart data={months} index=\"month\" series={[{ key: 'visits', label: '访问量' }]} />\n * <AreaChart stacked data={months} index=\"month\" series={channels} unit=\"万次\" />\n * <AreaChart stacked=\"percent\" data={months} index=\"month\" series={channels} />\n *\n * 坐标轴、十字线(带圆点)与提示框、图例、单位、加载与空状态、给读屏的数据表同 LineChart(见 XYChart)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { chartAreas } from './marks';\nimport type { LineCurves } from './shape';\nimport { XYChart, type XYChartKind, type XYChartProps } from './XYChart';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上 */\nexport interface AreaChartProps<T extends object> extends XYChartProps<T> {\n /** 堆叠:true 各系列依次叠起,'percent' 按占比叠满 100%(数值轴是百分比);默认重叠、半透明 */\n stacked?: boolean | 'percent';\n /**\n * 曲线的形状\n * @default 'monotone'\n */\n curve?: keyof LineCurves;\n /**\n * 面积的不透明度(0–1);默认重叠时 0.25、堆叠时 0.8\n */\n opacity?: number;\n}\n\n/** 面积图 */\nexport const AreaChart = _component(\n <T extends object>({\n stacked = false,\n curve = 'monotone',\n opacity,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n ...rest\n }: AreaChartProps<T>) => {\n const kind = _derived<XYChartKind<T>>({\n crosshairDots: true,\n stacked: stacked !== false,\n percent: stacked === 'percent',\n padding: { left: 12, right: 12, top: 8 },\n render: (context) =>\n chartAreas(context, context.series, {\n curve,\n stacked: stacked !== false,\n opacity: opacity ?? (stacked ? 0.8 : 0.25),\n }),\n });\n return () => <XYChart {...rest} _hiddenSeries={hiddenSeries} kind={kind} />;\n },\n);\n"],"mappings":";;;;;;;AA+BA,IAAa,YAAY,0BACvB,QAAA,SAMyB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WALb,KAAK;CAAA,MAAA,QAAAA,aAAA,QAAA,SACP,UAAU;CAAA,MAAA,UAAAA,aAAA,QAAA,SAAA;CAAA,MAAA,eAAAC,SAAA,QAAA,uBAEgC,CAAA,GAAE,KAAA,IAAA;CAAA,MACjD,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAIC,gBAA4B;EACpC,eAAe;EACf,SAAS,QAAA,UAAY;EACrB,SAAS,QAAA,UAAY;EACrB,SAAS;GAAE,MAAM;GAAI,OAAO;GAAI,KAAK;EAAE;EACvC,SAAS,YACP,WAAW,SAAS,QAAQ,QAAQ;GAClC,OAAK,MAAA;GACL,SAAS,QAAA,UAAY;GACrB,SAAS,QAAA,UAAY,QAAA,QAAU,KAAM;EACvC,CAAC;CACL,EAAC;CACD,aAAOC,YAAA,SAAAC,cAAmB,MAAI;EAAA,iBAAA,aAAA;EAAA,0BAAA,OAAA,OAAA,OAAA,MAAA,WAAA,aAAA,QAAA;EAAA,QAAA,KAAA;CAAA,CAAA,GAAA,IAAA;AAChC,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
package/dist/charts/BarChart.js
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
|
+
import { chartBars } from "./marks.js";
|
|
1
2
|
import { XYChart } from "./XYChart.js";
|
|
2
3
|
import { computed, createVNode } from "vue";
|
|
3
4
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
4
|
-
import { GroupedBar, StackedBar } from "@unovis/ts";
|
|
5
5
|
//#region src/charts/BarChart.tsx
|
|
6
|
-
/**
|
|
7
|
-
* 柱状图:每个类目一组柱子,系列并排(分组)或叠成一根(堆叠),可以横向;stacked="percent" 时每根叠满 100%(看构成)。
|
|
8
|
-
*
|
|
9
|
-
* <BarChart
|
|
10
|
-
* aria-label="各项目销售额"
|
|
11
|
-
* data={projects}
|
|
12
|
-
* index="name"
|
|
13
|
-
* series={[{ key: 'planned', label: '预期销售' }, { key: 'actual', label: '实际销售' }]}
|
|
14
|
-
* unit="万元"
|
|
15
|
-
* />
|
|
16
|
-
*
|
|
17
|
-
* 颜色、坐标轴、提示框、图例、读屏的数据表见 XYChart;悬停一个类目时提示框列出这一组的全部系列。
|
|
18
|
-
*/
|
|
19
6
|
/** 柱子的方向 */
|
|
20
7
|
/** 未声明的属性落到外层 div(role="figure")上;aria-label 是图表的名称 */
|
|
21
8
|
/** 柱状图:分组或堆叠,竖向或横向 */
|
|
@@ -27,45 +14,15 @@ var BarChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
27
14
|
const hiddenSeries = bindable(_props, "_hiddenSeries", () => [], _ctx.emit);
|
|
28
15
|
const rest = restProps(_props, _ctx, true);
|
|
29
16
|
const kind = computed(() => ({
|
|
17
|
+
band: true,
|
|
30
18
|
horizontal: orientation.value === "horizontal",
|
|
31
19
|
skeleton: "bars",
|
|
32
20
|
stacked: stacked.value !== false,
|
|
33
21
|
percent: stacked.value === "percent",
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
y: series.map(y),
|
|
39
|
-
color: (_row, position) => series[position]?.color,
|
|
40
|
-
roundedCorners: radius.value,
|
|
41
|
-
orientation: orientation.value,
|
|
42
|
-
events
|
|
43
|
-
};
|
|
44
|
-
if (stacked.value) {
|
|
45
|
-
const bars = instance("stacked", () => new StackedBar({
|
|
46
|
-
x,
|
|
47
|
-
y: []
|
|
48
|
-
}));
|
|
49
|
-
bars.setConfig({
|
|
50
|
-
...common,
|
|
51
|
-
barPadding: .4,
|
|
52
|
-
barMaxWidth: 48
|
|
53
|
-
});
|
|
54
|
-
return [bars];
|
|
55
|
-
}
|
|
56
|
-
const bars = instance("grouped", () => new GroupedBar({
|
|
57
|
-
x,
|
|
58
|
-
y: []
|
|
59
|
-
}));
|
|
60
|
-
bars.setConfig({
|
|
61
|
-
...common,
|
|
62
|
-
groupPadding: .3,
|
|
63
|
-
barPadding: .1,
|
|
64
|
-
groupMaxWidth: 96,
|
|
65
|
-
barMinHeight: 0
|
|
66
|
-
});
|
|
67
|
-
return [bars];
|
|
68
|
-
}
|
|
22
|
+
render: (context) => chartBars(context, context.series, {
|
|
23
|
+
stacked: stacked.value !== false,
|
|
24
|
+
radius: radius.value
|
|
25
|
+
})
|
|
69
26
|
}));
|
|
70
27
|
return () => createVNode(XYChart, mergeJsxProps(rest, {
|
|
71
28
|
"_hiddenSeries": hiddenSeries.value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BarChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/charts/BarChart.tsx"],"sourcesContent":["/**\n * 柱状图:每个类目一组柱子,系列并排(分组)或叠成一根(堆叠),可以横向;stacked=\"percent\" 时每根叠满 100%(看构成)。\n *\n * <BarChart\n * aria-label=\"各项目销售额\"\n * data={projects}\n * index=\"name\"\n * series={[{ key: 'planned', label: '预期销售' }, { key: 'actual', label: '实际销售' }]}\n * unit=\"万元\"\n * />\n *\n * 颜色、坐标轴、提示框、图例、读屏的数据表见 XYChart
|
|
1
|
+
{"version":3,"file":"BarChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_createVNode","_mergeProps"],"sources":["../../src/charts/BarChart.tsx"],"sourcesContent":["/**\n * 柱状图:每个类目一组柱子,系列并排(分组)或叠成一根(堆叠),可以横向;stacked=\"percent\" 时每根叠满 100%(看构成)。\n *\n * <BarChart\n * aria-label=\"各项目销售额\"\n * data={projects}\n * index=\"name\"\n * series={[{ key: 'planned', label: '预期销售' }, { key: 'actual', label: '实际销售' }]}\n * unit=\"万元\"\n * />\n *\n * 颜色、坐标轴、提示框、图例、读屏的数据表见 XYChart;悬停一个类目时这一格铺一层浅底,提示框列出这一组的全部系列。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { chartBars } from './marks';\nimport { XYChart, type XYChartKind, type XYChartProps } from './XYChart';\n\n/** 柱子的方向 */\nexport interface BarChartOrientations {\n /** 竖向的柱子(默认) */\n vertical: unknown;\n /** 横向的条:类目名较长、类目较多时 */\n horizontal: unknown;\n}\n\n/** 未声明的属性落到外层 div(role=\"figure\")上;aria-label 是图表的名称 */\nexport interface BarChartProps<T extends object> extends XYChartProps<T> {\n /** 堆叠:true 同一类目的系列叠成一根柱子,'percent' 按占比叠满 100%(数值轴是百分比);默认并排 */\n stacked?: boolean | 'percent';\n /** 方向,默认 vertical */\n orientation?: keyof BarChartOrientations;\n /** 柱子末端的圆角(px),默认 4 */\n radius?: number;\n}\n\n/** 柱状图:分组或堆叠,竖向或横向 */\nexport const BarChart = _component(\n <T extends object>({\n stacked = false,\n orientation = 'vertical',\n radius = 4,\n _hiddenSeries: hiddenSeries = _bindable<string[]>([]),\n ...rest\n }: BarChartProps<T>) => {\n const kind = _derived<XYChartKind<T>>({\n band: true,\n horizontal: orientation === 'horizontal',\n skeleton: 'bars',\n stacked: stacked !== false,\n percent: stacked === 'percent',\n render: (context) =>\n chartBars(context, context.series, { stacked: stacked !== false, radius }),\n });\n return () => <XYChart {...rest} _hiddenSeries={hiddenSeries} kind={kind} />;\n },\n);\n"],"mappings":";;;;;;;;AAoCA,IAAa,WAAW,0BACtB,QAAA,SAMwB;CAAA,MAAA,SAAA,CAAA;CAAA,MAAA,UAAAA,aAAA,QAAA,WALZ,KAAK;CAAA,MAAA,cAAAA,aAAA,QAAA,eACD,UAAU;CAAA,MAAA,SAAAA,aAAA,QAAA,UACf,CAAC;CAAA,MAAA,eAAAC,SAAA,QAAA,uBACwC,CAAA,GAAE,KAAA,IAAA;CAAA,MACjD,OAAIC,UAAA,QAAA,MAAA,IAAA;CAEP,MAAM,OAAIC,gBAA4B;EACpC,MAAM;EACN,YAAY,YAAA,UAAgB;EAC5B,UAAU;EACV,SAAS,QAAA,UAAY;EACrB,SAAS,QAAA,UAAY;EACrB,SAAS,YACP,UAAU,SAAS,QAAQ,QAAQ;GAAE,SAAS,QAAA,UAAY;GAAO,QAAM,OAAA;EAAC,CAAC;CAC7E,EAAC;CACD,aAAOC,YAAA,SAAAC,cAAmB,MAAI;EAAA,iBAAA,aAAA;EAAA,0BAAA,OAAA,OAAA,OAAA,MAAA,WAAA,aAAA,QAAA;EAAA,QAAA,KAAA;CAAA,CAAA,GAAA,IAAA;AAChC,GAAC;CAAA,MAAA;CAAA,OAAA;EAAA;EAAA;EAAA;EAAA;EAAA;CAAA;AAAA,CACH"}
|
|
@@ -39,9 +39,14 @@ export interface ChordChartProps extends PartProps<'div', 'role' | 'aria-busy'>,
|
|
|
39
39
|
/** 没有数据时显示的内容,默认是“暂无数据” */
|
|
40
40
|
empty?: VNodeChild;
|
|
41
41
|
}
|
|
42
|
-
/** ChordChart
|
|
42
|
+
/** ChordChart 的样式:弧、弦、名字、骨架 */
|
|
43
43
|
export declare const chordChartStyles: Readonly<{
|
|
44
|
-
|
|
44
|
+
label: css.CompiledStyles;
|
|
45
|
+
link: css.CompiledStyles;
|
|
46
|
+
linkActive: css.CompiledStyles;
|
|
47
|
+
linkFaded: css.CompiledStyles;
|
|
48
|
+
node: css.CompiledStyles;
|
|
49
|
+
nodeFaded: css.CompiledStyles;
|
|
45
50
|
skeleton: css.CompiledStyles;
|
|
46
51
|
}>;
|
|
47
52
|
/** 弦图 */
|
|
@@ -1,45 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { svgNumber } from "../utils/data/number.js";
|
|
2
|
+
import { t } from "../config/theme/tokens.js";
|
|
2
3
|
import { useLang } from "../config/context.js";
|
|
3
4
|
import { useFormat } from "../config/lang/format.js";
|
|
4
5
|
import { Skeleton } from "../feedback/Skeleton.js";
|
|
6
|
+
import { ChartTooltipBox, chartSvgStyles, pointerIn, usePlotArea } from "./plot.js";
|
|
7
|
+
import { arcPath, polarPoint, ribbonPath } from "./shape.js";
|
|
5
8
|
import { ChartFrame, chartTooltip, useChartValueText } from "./frame.js";
|
|
9
|
+
import { estimateTextWidth } from "./text-size.js";
|
|
6
10
|
import { flowData, resolveFlowNodes } from "./flow.js";
|
|
7
|
-
import {
|
|
11
|
+
import { chordLayout } from "./layout/chord.js";
|
|
8
12
|
import { computed, createVNode, shallowRef } from "vue";
|
|
9
13
|
import { _component, bindable, mergeJsxProps, readonlyProp, restProps } from "@zerodep-dev/vue-tsx-pro-tsx";
|
|
10
14
|
import { css } from "@zerodep-dev/vue-tsx-pro-tsx/styles";
|
|
11
|
-
import { ChordDiagram, ChordLabelAlignment } from "@unovis/ts";
|
|
12
15
|
//#region src/charts/ChordChart.tsx
|
|
13
|
-
/**
|
|
14
|
-
* 弦图:节点排成一圈,两两之间的流量画成弦,看几方之间相互往来的多少(部门协作、地区间人口流动、贸易往来)。
|
|
15
|
-
*
|
|
16
|
-
* <ChordChart aria-label="部门协作" nodes={departments} links={collaborations} />
|
|
17
|
-
*
|
|
18
|
-
* 数据同 SankeyChart(节点 { id, label?, color? },流向 { source, target, value });弦取起点节点的颜色。
|
|
19
|
-
* 悬停一段弧出这个节点的总量,悬停一根弦出“起点 → 终点”的流量;点图例隐藏一个节点,连同它的弦。
|
|
20
|
-
* 单位、加载与空状态、给读屏的数据表(每条流向一行)同其他图表(见 ChartFrame)。
|
|
21
|
-
*/
|
|
22
16
|
/** 未声明的属性落到外层 div(role="figure")上,aria-label 是图表的名称 */
|
|
23
|
-
/** ChordChart
|
|
17
|
+
/** ChordChart 的样式:弧、弦、名字、骨架 */
|
|
24
18
|
var chordChartStyles = css.create({
|
|
25
|
-
root: {
|
|
26
|
-
"--vis-chord-diagram-link-opacity": "0.45",
|
|
27
|
-
"--vis-chord-diagram-link-stroke-color": colors.surface,
|
|
28
|
-
"--vis-chord-diagram-link-stroke-opacity": "0.6",
|
|
29
|
-
"--vis-chord-diagram-link-highlighted-opacity": "0.85",
|
|
30
|
-
"--vis-chord-diagram-link-dimmed-opacity": "0.12",
|
|
31
|
-
"--vis-chord-diagram-node-dimmed-opacity": "0.3",
|
|
32
|
-
"--vis-chord-diagram-label-text-font-size": fontSizes.xs
|
|
33
|
-
},
|
|
34
19
|
skeleton: {
|
|
35
20
|
display: "block",
|
|
36
21
|
height: "100%",
|
|
37
22
|
aspectRatio: "1",
|
|
38
23
|
marginInline: "auto",
|
|
39
24
|
borderRadius: "50%"
|
|
25
|
+
},
|
|
26
|
+
node: { transition: `opacity ${t.durations.sm} ${t.easings.standard}` },
|
|
27
|
+
link: {
|
|
28
|
+
fillOpacity: .45,
|
|
29
|
+
stroke: "_surface",
|
|
30
|
+
strokeOpacity: .6,
|
|
31
|
+
strokeWidth: .5,
|
|
32
|
+
transition: `fill-opacity ${t.durations.sm} ${t.easings.standard}`
|
|
33
|
+
},
|
|
34
|
+
linkActive: { fillOpacity: .85 },
|
|
35
|
+
linkFaded: { fillOpacity: .12 },
|
|
36
|
+
nodeFaded: { opacity: .3 },
|
|
37
|
+
label: {
|
|
38
|
+
fill: "_textMuted",
|
|
39
|
+
fontSize: "_xs"
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
|
-
/**
|
|
42
|
+
/** 弧的粗细、弧与弦之间的空、弧之间的空隙(弧度) */
|
|
43
|
+
var ARC_WIDTH = 14;
|
|
44
|
+
var ARC_GAP = 3;
|
|
45
|
+
var PAD_ANGLE = .04;
|
|
46
|
+
/** 悬停的是弧还是弦 */
|
|
43
47
|
/** 弦图 */
|
|
44
48
|
var ChordChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
45
49
|
const _cache = [];
|
|
@@ -53,7 +57,6 @@ var ChordChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
53
57
|
const loading = readonlyProp(_props, "loading", false);
|
|
54
58
|
const hiddenNodes = bindable(_props, "_hiddenNodes", () => [], _ctx.emit);
|
|
55
59
|
const empty = readonlyProp(_props, "empty");
|
|
56
|
-
const sx = readonlyProp(_props, "sx");
|
|
57
60
|
const rest = restProps(_props, _ctx, true);
|
|
58
61
|
const lang = useLang();
|
|
59
62
|
const format = useFormat();
|
|
@@ -64,46 +67,130 @@ var ChordChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
64
67
|
unit: unit.value
|
|
65
68
|
}));
|
|
66
69
|
const labelOf = (id) => resolved.value.get(id)?.label ?? id;
|
|
70
|
+
const area = usePlotArea();
|
|
71
|
+
let hovered = shallowRef(null);
|
|
67
72
|
function toggle(id) {
|
|
68
73
|
hiddenNodes.value = hiddenNodes.value.includes(id) ? hiddenNodes.value.filter((item) => item !== id) : [...hiddenNodes.value, id];
|
|
69
74
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
const layout = computed(() => {
|
|
76
|
+
const data = flowData(visible.value, links.value);
|
|
77
|
+
const order = new Map(data.nodes.map((node, position) => [node.id, position]));
|
|
78
|
+
const { groups, chords } = chordLayout(data.nodes.length, data.links.map((link) => ({
|
|
79
|
+
source: order.get(link.source),
|
|
80
|
+
target: order.get(link.target),
|
|
81
|
+
value: link.amount
|
|
82
|
+
})), PAD_ANGLE);
|
|
83
|
+
return {
|
|
84
|
+
nodes: data.nodes,
|
|
85
|
+
flows: data.links,
|
|
86
|
+
groups,
|
|
87
|
+
chords
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
function onPointermove(event) {
|
|
91
|
+
const target = event.target.closest?.("[data-node],[data-link]");
|
|
92
|
+
if (!target) {
|
|
93
|
+
hovered.value = null;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const { x, y } = pointerIn(event, event.currentTarget);
|
|
97
|
+
const node = target.getAttribute("data-node");
|
|
98
|
+
hovered.value = node === null ? {
|
|
99
|
+
kind: "link",
|
|
100
|
+
index: Number(target.getAttribute("data-link")),
|
|
101
|
+
x,
|
|
102
|
+
y
|
|
103
|
+
} : {
|
|
104
|
+
kind: "node",
|
|
105
|
+
index: Number(node),
|
|
106
|
+
x,
|
|
107
|
+
y
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** 弦与悬停的弧相连(悬停弦时只有它自己):true 突出、false 变淡、undefined 没有悬停 */
|
|
111
|
+
const chordState = (index) => {
|
|
112
|
+
const current = hovered.value;
|
|
113
|
+
if (!current) return void 0;
|
|
114
|
+
if (current.kind === "link") return current.index === index;
|
|
115
|
+
const flow = layout.value.flows[index];
|
|
116
|
+
const id = layout.value.nodes[current.index]?.id;
|
|
117
|
+
return flow.source === id || flow.target === id;
|
|
118
|
+
};
|
|
119
|
+
function renderPlot() {
|
|
120
|
+
const { width, height: plotHeight } = area;
|
|
121
|
+
const labelRoom = legend.value ? 4 : Math.max(0, ...layout.value.nodes.map((node) => estimateTextWidth(node.label))) + 12;
|
|
122
|
+
const outer = Math.max(0, Math.min(width / 2 - labelRoom, plotHeight / 2 - (legend.value ? 4 : 20)));
|
|
123
|
+
const inner = Math.max(0, outer - ARC_WIDTH);
|
|
124
|
+
const current = hovered.value;
|
|
125
|
+
return createVNode("svg", mergeJsxProps({
|
|
126
|
+
"width": width,
|
|
127
|
+
"height": plotHeight
|
|
128
|
+
}, css.attrs(chartSvgStyles.svg), {
|
|
129
|
+
"onPointermove": onPointermove,
|
|
130
|
+
"onPointerleave": _cache[0] || (_cache[0] = () => hovered.value = null)
|
|
131
|
+
}), [createVNode("g", mergeJsxProps({ "transform": `translate(${svgNumber(width / 2)},${svgNumber(plotHeight / 2)})` }, css.attrs(chartSvgStyles.fadeIn)), [createVNode("g", { "data-part": "links" }, [layout.value.chords.map((chord) => {
|
|
132
|
+
const state = chordState(chord.index);
|
|
133
|
+
const source = visible.value.get(layout.value.flows[chord.index].source);
|
|
134
|
+
return createVNode("path", mergeJsxProps({
|
|
135
|
+
"key": chord.index,
|
|
136
|
+
"data-part": "link",
|
|
137
|
+
"data-link": chord.index,
|
|
138
|
+
"d": ribbonPath(Math.max(0, inner - ARC_GAP), chord.source, chord.target)
|
|
139
|
+
}, css.attrs(chordChartStyles.link, chartSvgStyles.fill(source.color), state === true && chordChartStyles.linkActive, state === false && chordChartStyles.linkFaded)), null);
|
|
140
|
+
})]), layout.value.groups.map((group, index) => {
|
|
141
|
+
const node = layout.value.nodes[index];
|
|
142
|
+
const middle = (group.start + group.end) / 2;
|
|
143
|
+
const [x, y] = polarPoint(outer + 8, middle);
|
|
144
|
+
const faded = current?.kind === "node" && current.index !== index;
|
|
145
|
+
return createVNode("g", { "key": node.id }, [createVNode("path", mergeJsxProps({
|
|
146
|
+
"data-part": "node",
|
|
147
|
+
"data-node": index,
|
|
148
|
+
"d": arcPath({
|
|
149
|
+
inner,
|
|
150
|
+
outer,
|
|
151
|
+
start: group.start,
|
|
152
|
+
end: group.end,
|
|
153
|
+
corner: 2
|
|
154
|
+
})
|
|
155
|
+
}, css.attrs(chordChartStyles.node, chartSvgStyles.fill(node.color), faded && chordChartStyles.nodeFaded)), null), !legend.value && createVNode("text", mergeJsxProps({
|
|
156
|
+
"x": svgNumber(x),
|
|
157
|
+
"y": svgNumber(y),
|
|
158
|
+
"text-anchor": Math.abs(x) < outer * .2 ? "middle" : x > 0 ? "start" : "end",
|
|
159
|
+
"dominant-baseline": "central"
|
|
160
|
+
}, css.attrs(chordChartStyles.label, chartSvgStyles.noPointer)), [node.label])]);
|
|
161
|
+
})])]);
|
|
162
|
+
}
|
|
163
|
+
const tip = () => {
|
|
164
|
+
const current = hovered.value;
|
|
165
|
+
if (!tooltip.value || !current) return null;
|
|
166
|
+
if (current.kind === "node") {
|
|
167
|
+
const node = layout.value.nodes[current.index];
|
|
168
|
+
const group = layout.value.groups[current.index];
|
|
169
|
+
if (!node || !group) return null;
|
|
87
170
|
return {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}])),
|
|
96
|
-
[ChordDiagram.selectors.link]: (ribbon) => chart.tooltip(chartTooltip(lang.chartFlowLabel(ribbon.data.source.label, ribbon.data.target.label), [{
|
|
97
|
-
label: lang.chartValue,
|
|
98
|
-
color: ribbon.data.source.color,
|
|
99
|
-
value: valueText(ribbon.data.value)
|
|
100
|
-
}]))
|
|
101
|
-
}
|
|
171
|
+
x: current.x,
|
|
172
|
+
y: current.y,
|
|
173
|
+
content: chartTooltip(node.label, [{
|
|
174
|
+
label: lang.chartTotal,
|
|
175
|
+
color: node.color,
|
|
176
|
+
value: valueText(group.value)
|
|
177
|
+
}])
|
|
102
178
|
};
|
|
103
179
|
}
|
|
104
|
-
|
|
180
|
+
const flow = layout.value.flows[current.index];
|
|
181
|
+
if (!flow) return null;
|
|
182
|
+
const source = resolved.value.get(flow.source);
|
|
183
|
+
return {
|
|
184
|
+
x: current.x,
|
|
185
|
+
y: current.y,
|
|
186
|
+
content: chartTooltip(lang.chartFlowLabel(source.label, labelOf(flow.target)), [{
|
|
187
|
+
label: lang.chartValue,
|
|
188
|
+
color: source.color,
|
|
189
|
+
value: valueText(flow.value)
|
|
190
|
+
}])
|
|
191
|
+
};
|
|
192
|
+
};
|
|
105
193
|
return () => createVNode(ChartFrame, mergeJsxProps(rest, {
|
|
106
|
-
"sx": [chordChartStyles.root, sx.value],
|
|
107
194
|
"unit": unit.value,
|
|
108
195
|
"height": height.value,
|
|
109
196
|
"legend": legend.value ? [...resolved.value.values()].map((node) => ({
|
|
@@ -124,7 +211,12 @@ var ChordChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
124
211
|
cells: [format.number(link.value, valueFormat.value)]
|
|
125
212
|
}))
|
|
126
213
|
},
|
|
127
|
-
"plotRef":
|
|
214
|
+
"plotRef": area.ref,
|
|
215
|
+
"plot": area.ready ? [renderPlot(), createVNode(ChartTooltipBox, {
|
|
216
|
+
"key": "tooltip",
|
|
217
|
+
"tip": tip(),
|
|
218
|
+
"width": area.width
|
|
219
|
+
}, null)] : null
|
|
128
220
|
}), null);
|
|
129
221
|
}, {
|
|
130
222
|
name: "ChordChart",
|
|
@@ -139,8 +231,7 @@ var ChordChart = /*#__PURE__*/ _component((_props, _ctx) => {
|
|
|
139
231
|
"loading",
|
|
140
232
|
"_hiddenNodes",
|
|
141
233
|
"onUpdate:_hiddenNodes",
|
|
142
|
-
"empty"
|
|
143
|
-
"sx"
|
|
234
|
+
"empty"
|
|
144
235
|
]
|
|
145
236
|
});
|
|
146
237
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChordChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/charts/ChordChart.tsx"],"sourcesContent":["/**\n * 弦图:节点排成一圈,两两之间的流量画成弦,看几方之间相互往来的多少(部门协作、地区间人口流动、贸易往来)。\n *\n * <ChordChart aria-label=\"部门协作\" nodes={departments} links={collaborations} />\n *\n * 数据同 SankeyChart(节点 { id, label?, color? },流向 { source, target, value });弦取起点节点的颜色。\n * 悬停一段弧出这个节点的总量,悬停一根弦出“起点 → 终点”的流量;点图例隐藏一个节点,连同它的弦。\n * 单位、加载与空状态、给读屏的数据表(每条流向一行)同其他图表(见 ChartFrame)。\n */\nimport { ChordDiagram, ChordLabelAlignment } from '@unovis/ts';\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { colors, fontSizes } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport type { NumericValue } from '../utils/data/numeric';\nimport type { PartProps } from '../utils/props';\nimport { flowData, resolveFlowNodes, type FlowLink, type FlowNode } from './flow';\nimport { ChartFrame, chartTooltip, useChartValueText, type ChartFrameParts } from './frame';\nimport { useSingleChart, type SingleChart } from './single';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上,aria-label 是图表的名称 */\nexport interface ChordChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 节点 */\n nodes: readonly FlowNode[];\n /** 流向 */\n links: readonly FlowLink[];\n /** 数值的格式(可缩放,如以万元为单位):提示框、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 320\n */\n height?: number | string;\n /**\n * 图例:点一下隐藏节点;关掉时节点名写在弧的外侧\n * @default true\n */\n legend?: boolean;\n /**\n * 悬停时的提示框\n * @default true\n */\n tooltip?: boolean;\n /**\n * 加载中:绘图区显示一个圆形的骨架,带 aria-busy\n * @default false\n */\n loading?: boolean;\n /** 隐藏的节点(存 id):点图例时写回,父级可以写 _hiddenNodes={ids} */\n _hiddenNodes?: string[];\n /** 没有数据时显示的内容,默认是“暂无数据” */\n empty?: VNodeChild;\n}\n\n/** ChordChart 的样式:root(--vis-chord-diagram-* 主题变量)、skeleton */\nexport const chordChartStyles = css.create({\n root: {\n '--vis-chord-diagram-link-opacity': '0.45',\n '--vis-chord-diagram-link-stroke-color': colors.surface,\n '--vis-chord-diagram-link-stroke-opacity': '0.6',\n '--vis-chord-diagram-link-highlighted-opacity': '0.85',\n '--vis-chord-diagram-link-dimmed-opacity': '0.12',\n '--vis-chord-diagram-node-dimmed-opacity': '0.3',\n '--vis-chord-diagram-label-text-font-size': fontSizes.xs,\n },\n skeleton: {\n display: 'block',\n height: '100%',\n aspectRatio: '1',\n marginInline: 'auto',\n borderRadius: '50%',\n },\n});\n\n/** 交给 Unovis 的节点、流向 */\ntype Data = ReturnType<typeof flowData>;\ntype Node = Data['nodes'][number];\ntype Link = Data['links'][number];\n\n/** 弦图 */\nexport const ChordChart = _component(\n ({\n nodes,\n links,\n valueFormat,\n unit,\n height = 320,\n legend = true,\n tooltip = true,\n loading = false,\n _hiddenNodes: hiddenNodes = _bindable<string[]>([]),\n empty,\n sx,\n ...rest\n }: ChordChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveFlowNodes(nodes));\n const visible = _derived(new Map([...resolved].filter(([id]) => !hiddenNodes.includes(id))));\n const valueText = useChartValueText(() => ({ valueFormat, unit }));\n const labelOf = (id: string) => resolved.get(id)?.label ?? id;\n\n function toggle(id: string) {\n hiddenNodes = hiddenNodes.includes(id)\n ? hiddenNodes.filter((item) => item !== id)\n : [...hiddenNodes, id];\n }\n\n let plot = _state.raw<HTMLElement | null>(null);\n const chart: SingleChart = useSingleChart<{ nodes: Node[]; links?: Link[] }>(() => ({\n element: plot,\n ready: !loading && nodes.length > 0,\n tooltip,\n build: (instance) => {\n const chord = instance(\n 'chord',\n () => new ChordDiagram<Node, Link>({ linkValue: (link) => link.amount }),\n );\n chord.setConfig({\n linkValue: (link) => link.amount,\n nodeColor: (node) => (node as Node).color,\n linkColor: (link) => (link.source as Node).color,\n // 有图例时不在弧旁写名字:径向排的中文在上下两侧是竖着的,不好读\n nodeLabel: (node) => (legend ? '' : (node as Node).label),\n padAngle: 0.04,\n nodeWidth: 14,\n nodeLabelAlignment: ChordLabelAlignment.Perpendicular,\n nodeLabelColor: () => colors.textMuted,\n });\n return {\n component: chord,\n data: flowData(visible, links),\n triggers: {\n [ChordDiagram.selectors.node]: (node: { data: Node; _state: { value?: number } }) =>\n chart.tooltip(\n chartTooltip(node.data.label, [\n {\n label: lang.chartTotal,\n color: node.data.color,\n value: valueText(node._state.value),\n },\n ]),\n ),\n [ChordDiagram.selectors.link]: (ribbon: {\n data: { source: Node; target: Node; value: NumericValue };\n }) =>\n chart.tooltip(\n chartTooltip(\n lang.chartFlowLabel(ribbon.data.source.label, ribbon.data.target.label),\n [\n {\n label: lang.chartValue,\n color: ribbon.data.source.color,\n value: valueText(ribbon.data.value),\n },\n ],\n ),\n ),\n },\n };\n },\n }));\n\n return () => (\n <ChartFrame\n {...rest}\n sx={[chordChartStyles.root, sx]}\n unit={unit}\n height={height}\n legend={\n legend\n ? [...resolved.values()].map((node) => ({\n key: node.id,\n label: node.label,\n color: node.color,\n }))\n : []\n }\n hiddenKeys={hiddenNodes}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={chordChartStyles.skeleton} />}\n isEmpty={nodes.length === 0}\n empty={empty}\n table={{\n columns: [lang.chartFlow, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: links\n .filter((link) => visible.has(link.source) && visible.has(link.target))\n .map((link) => ({\n header: lang.chartFlowLabel(labelOf(link.source), labelOf(link.target)),\n cells: [format.number(link.value, valueFormat)],\n })),\n }}\n plotRef={(element) => (plot = element)}\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChordChart.js","names":["_vtp_readonlyProp","_vtp_bindable","_vtp_restProps","_vue_computed","_vue_shallowRef","_createVNode","_mergeProps"],"sources":["../../src/charts/ChordChart.tsx"],"sourcesContent":["/**\n * 弦图:节点排成一圈,两两之间的流量画成弦,看几方之间相互往来的多少(部门协作、地区间人口流动、贸易往来)。\n *\n * <ChordChart aria-label=\"部门协作\" nodes={departments} links={collaborations} />\n *\n * 数据同 SankeyChart(节点 { id, label?, color? },流向 { source, target, value });弦取起点节点的颜色。\n * 悬停一段弧出这个节点的总量并突出它的弦,悬停一根弦出“起点 → 终点”的流量;点图例隐藏一个节点,连同它的弦。\n * 布局见 chordLayout:弧长是流入加流出,弦的两端都按流量定宽。\n * 单位、加载与空状态、给读屏的数据表(每条流向一行)同其他图表(见 ChartFrame)。\n */\nimport { _component } from '@zerodep-dev/vue-tsx-pro-tsx';\nimport { css } from '@zerodep-dev/vue-tsx-pro-tsx/styles';\nimport type { VNodeChild } from 'vue';\nimport { useLang } from '../config/context';\nimport { useFormat, type NumericFormat } from '../config/lang/format';\nimport { t } from '../config/theme/tokens';\nimport { Skeleton } from '../feedback/Skeleton';\nimport { svgNumber } from '../utils/data/number';\nimport type { PartProps } from '../utils/props';\nimport { flowData, resolveFlowNodes, type FlowLink, type FlowNode } from './flow';\nimport { ChartFrame, chartTooltip, useChartValueText, type ChartFrameParts } from './frame';\nimport { chordLayout } from './layout/chord';\nimport { ChartTooltipBox, chartSvgStyles, pointerIn, usePlotArea, type ChartTip } from './plot';\nimport { arcPath, polarPoint, ribbonPath } from './shape';\nimport { estimateTextWidth } from './text-size';\n\n/** 未声明的属性落到外层 div(role=\"figure\")上,aria-label 是图表的名称 */\nexport interface ChordChartProps extends PartProps<'div', 'role' | 'aria-busy'>, ChartFrameParts {\n /** 节点 */\n nodes: readonly FlowNode[];\n /** 流向 */\n links: readonly FlowLink[];\n /** 数值的格式(可缩放,如以万元为单位):提示框、数据表共用 */\n valueFormat?: NumericFormat;\n /** 单位:显示在左上方,数值后面带上 */\n unit?: string;\n /**\n * 绘图区的高度;数字按 px\n * @default 320\n */\n height?: number | string;\n /**\n * 图例:点一下隐藏节点;关掉时节点名写在弧的外侧\n * @default true\n */\n legend?: boolean;\n /**\n * 悬停时的提示框\n * @default true\n */\n tooltip?: boolean;\n /**\n * 加载中:绘图区显示一个圆形的骨架,带 aria-busy\n * @default false\n */\n loading?: boolean;\n /** 隐藏的节点(存 id):点图例时写回,父级可以写 _hiddenNodes={ids} */\n _hiddenNodes?: string[];\n /** 没有数据时显示的内容,默认是“暂无数据” */\n empty?: VNodeChild;\n}\n\n/** ChordChart 的样式:弧、弦、名字、骨架 */\nexport const chordChartStyles = css.create({\n skeleton: {\n display: 'block',\n height: '100%',\n aspectRatio: '1',\n marginInline: 'auto',\n borderRadius: '50%',\n },\n node: { transition: `opacity ${t.durations.sm} ${t.easings.standard}` },\n link: {\n fillOpacity: 0.45,\n stroke: '_surface',\n strokeOpacity: 0.6,\n strokeWidth: 0.5,\n transition: `fill-opacity ${t.durations.sm} ${t.easings.standard}`,\n },\n linkActive: { fillOpacity: 0.85 },\n linkFaded: { fillOpacity: 0.12 },\n nodeFaded: { opacity: 0.3 },\n label: { fill: '_textMuted', fontSize: '_xs' },\n});\n\n/** 弧的粗细、弧与弦之间的空、弧之间的空隙(弧度) */\nconst ARC_WIDTH = 14;\nconst ARC_GAP = 3;\nconst PAD_ANGLE = 0.04;\n\n/** 悬停的是弧还是弦 */\ninterface ChordHover {\n kind: 'node' | 'link';\n index: number;\n x: number;\n y: number;\n}\n\n/** 弦图 */\nexport const ChordChart = _component(\n ({\n nodes,\n links,\n valueFormat,\n unit,\n height = 320,\n legend = true,\n tooltip = true,\n loading = false,\n _hiddenNodes: hiddenNodes = _bindable<string[]>([]),\n empty,\n ...rest\n }: ChordChartProps) => {\n const lang = useLang();\n const format = useFormat();\n const resolved = _derived(resolveFlowNodes(nodes));\n const visible = _derived(new Map([...resolved].filter(([id]) => !hiddenNodes.includes(id))));\n const valueText = useChartValueText(() => ({ valueFormat, unit }));\n const labelOf = (id: string) => resolved.get(id)?.label ?? id;\n const area = usePlotArea();\n let hovered = _state.raw<ChordHover | null>(null);\n\n function toggle(id: string) {\n hiddenNodes = hiddenNodes.includes(id)\n ? hiddenNodes.filter((item) => item !== id)\n : [...hiddenNodes, id];\n }\n\n const layout = _derived.by(() => {\n const data = flowData(visible, links);\n const order = new Map(data.nodes.map((node, position) => [node.id, position]));\n const { groups, chords } = chordLayout(\n data.nodes.length,\n data.links.map((link) => ({\n source: order.get(link.source)!,\n target: order.get(link.target)!,\n value: link.amount,\n })),\n PAD_ANGLE,\n );\n return { nodes: data.nodes, flows: data.links, groups, chords };\n });\n\n function onPointermove(event: PointerEvent) {\n const target = (event.target as Element).closest?.('[data-node],[data-link]');\n if (!target) {\n hovered = null;\n return;\n }\n const { x, y } = pointerIn(event, event.currentTarget as Element);\n const node = target.getAttribute('data-node');\n hovered =\n node === null\n ? { kind: 'link', index: Number(target.getAttribute('data-link')), x, y }\n : { kind: 'node', index: Number(node), x, y };\n }\n\n /** 弦与悬停的弧相连(悬停弦时只有它自己):true 突出、false 变淡、undefined 没有悬停 */\n const chordState = (index: number) => {\n const current = hovered;\n if (!current) return undefined;\n if (current.kind === 'link') return current.index === index;\n const flow = layout.flows[index]!;\n const id = layout.nodes[current.index]?.id;\n return flow.source === id || flow.target === id;\n };\n\n function renderPlot() {\n const { width, height: plotHeight } = area;\n // 没有图例时名字写在弧外:留出最长的名字\n const labelRoom = legend\n ? 4\n : Math.max(0, ...layout.nodes.map((node) => estimateTextWidth(node.label))) + 12;\n const outer = Math.max(\n 0,\n Math.min(width / 2 - labelRoom, plotHeight / 2 - (legend ? 4 : 20)),\n );\n const inner = Math.max(0, outer - ARC_WIDTH);\n const current = hovered;\n return (\n <svg\n width={width}\n height={plotHeight}\n {...css.attrs(chartSvgStyles.svg)}\n onPointermove={onPointermove}\n onPointerleave={() => (hovered = null)}\n >\n <g\n transform={`translate(${svgNumber(width / 2)},${svgNumber(plotHeight / 2)})`}\n {...css.attrs(chartSvgStyles.fadeIn)}\n >\n <g data-part=\"links\">\n {layout.chords.map((chord) => {\n const state = chordState(chord.index);\n const source = visible.get(layout.flows[chord.index]!.source)!;\n return (\n <path\n key={chord.index}\n data-part=\"link\"\n data-link={chord.index}\n d={ribbonPath(Math.max(0, inner - ARC_GAP), chord.source, chord.target)}\n {...css.attrs(\n chordChartStyles.link,\n chartSvgStyles.fill(source.color),\n state === true && chordChartStyles.linkActive,\n state === false && chordChartStyles.linkFaded,\n )}\n />\n );\n })}\n </g>\n {layout.groups.map((group, index) => {\n const node = layout.nodes[index]!;\n const middle = (group.start + group.end) / 2;\n const [x, y] = polarPoint(outer + 8, middle);\n const faded = current?.kind === 'node' && current.index !== index;\n return (\n <g key={node.id}>\n <path\n data-part=\"node\"\n data-node={index}\n d={arcPath({ inner, outer, start: group.start, end: group.end, corner: 2 })}\n {...css.attrs(\n chordChartStyles.node,\n chartSvgStyles.fill(node.color),\n faded && chordChartStyles.nodeFaded,\n )}\n />\n {!legend && (\n <text\n x={svgNumber(x)}\n y={svgNumber(y)}\n // 名字横着写:右半圈左对齐、左半圈右对齐,上下两端居中\n text-anchor={Math.abs(x) < outer * 0.2 ? 'middle' : x > 0 ? 'start' : 'end'}\n dominant-baseline=\"central\"\n {...css.attrs(chordChartStyles.label, chartSvgStyles.noPointer)}\n >\n {node.label}\n </text>\n )}\n </g>\n );\n })}\n </g>\n </svg>\n );\n }\n\n const tip = (): ChartTip | null => {\n const current = hovered;\n if (!tooltip || !current) return null;\n if (current.kind === 'node') {\n const node = layout.nodes[current.index];\n const group = layout.groups[current.index];\n if (!node || !group) return null;\n return {\n x: current.x,\n y: current.y,\n content: chartTooltip(node.label, [\n { label: lang.chartTotal, color: node.color, value: valueText(group.value) },\n ]),\n };\n }\n const flow = layout.flows[current.index];\n if (!flow) return null;\n const source = resolved.get(flow.source)!;\n return {\n x: current.x,\n y: current.y,\n content: chartTooltip(lang.chartFlowLabel(source.label, labelOf(flow.target)), [\n { label: lang.chartValue, color: source.color, value: valueText(flow.value) },\n ]),\n };\n };\n\n return () => (\n <ChartFrame\n {...rest}\n unit={unit}\n height={height}\n legend={\n legend\n ? [...resolved.values()].map((node) => ({\n key: node.id,\n label: node.label,\n color: node.color,\n }))\n : []\n }\n hiddenKeys={hiddenNodes}\n onLegendToggle={toggle}\n loading={loading}\n skeleton={<Skeleton sx={chordChartStyles.skeleton} />}\n isEmpty={nodes.length === 0}\n empty={empty}\n table={{\n columns: [lang.chartFlow, unit ? `${lang.chartValue}(${unit})` : lang.chartValue],\n rows: links\n .filter((link) => visible.has(link.source) && visible.has(link.target))\n .map((link) => ({\n header: lang.chartFlowLabel(labelOf(link.source), labelOf(link.target)),\n cells: [format.number(link.value, valueFormat)],\n })),\n }}\n plotRef={area.ref}\n plot={\n area.ready\n ? [renderPlot(), <ChartTooltipBox key=\"tooltip\" tip={tip()} width={area.width} />]\n : null\n }\n />\n );\n },\n);\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { NumericFormat } from '../config/lang/format';
|
|
2
|
-
import
|
|
2
|
+
import type { LineDots } from './LineChart';
|
|
3
3
|
import type { ChartSeries } from './series';
|
|
4
|
+
import type { LineCurves } from './shape';
|
|
4
5
|
import { type XYChartProps } from './XYChart';
|
|
5
6
|
/** 组合图的一个系列 */
|
|
6
7
|
export interface ComboSeries<T> extends ChartSeries<T> {
|