@zerodep-dev/vue-tsx-pro-ui 0.3.3 → 0.4.0

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.
Files changed (108) hide show
  1. package/dist/charts/AreaChart.d.ts +1 -1
  2. package/dist/charts/AreaChart.js +6 -48
  3. package/dist/charts/AreaChart.js.map +1 -1
  4. package/dist/charts/BarChart.js +6 -49
  5. package/dist/charts/BarChart.js.map +1 -1
  6. package/dist/charts/ChordChart.d.ts +7 -2
  7. package/dist/charts/ChordChart.js +151 -60
  8. package/dist/charts/ChordChart.js.map +1 -1
  9. package/dist/charts/ComboChart.d.ts +2 -1
  10. package/dist/charts/ComboChart.js +17 -93
  11. package/dist/charts/ComboChart.js.map +1 -1
  12. package/dist/charts/DonutChart.d.ts +6 -1
  13. package/dist/charts/DonutChart.js +134 -51
  14. package/dist/charts/DonutChart.js.map +1 -1
  15. package/dist/charts/FunnelChart.js.map +1 -1
  16. package/dist/charts/GraphChart.d.ts +22 -10
  17. package/dist/charts/GraphChart.js +415 -175
  18. package/dist/charts/GraphChart.js.map +1 -1
  19. package/dist/charts/LineChart.d.ts +1 -29
  20. package/dist/charts/LineChart.js +6 -54
  21. package/dist/charts/LineChart.js.map +1 -1
  22. package/dist/charts/MapChart.d.ts +21 -48
  23. package/dist/charts/MapChart.js +426 -353
  24. package/dist/charts/MapChart.js.map +1 -1
  25. package/dist/charts/RadarChart.js.map +1 -1
  26. package/dist/charts/SankeyChart.d.ts +7 -2
  27. package/dist/charts/SankeyChart.js +164 -76
  28. package/dist/charts/SankeyChart.js.map +1 -1
  29. package/dist/charts/ScatterChart.d.ts +7 -1
  30. package/dist/charts/ScatterChart.js +45 -30
  31. package/dist/charts/ScatterChart.js.map +1 -1
  32. package/dist/charts/TimelineChart.d.ts +8 -1
  33. package/dist/charts/TimelineChart.js +141 -89
  34. package/dist/charts/TimelineChart.js.map +1 -1
  35. package/dist/charts/TreemapChart.d.ts +6 -0
  36. package/dist/charts/TreemapChart.js +174 -58
  37. package/dist/charts/TreemapChart.js.map +1 -1
  38. package/dist/charts/WaterfallChart.d.ts +6 -7
  39. package/dist/charts/WaterfallChart.js +46 -51
  40. package/dist/charts/WaterfallChart.js.map +1 -1
  41. package/dist/charts/XYChart.d.ts +44 -35
  42. package/dist/charts/XYChart.js +493 -281
  43. package/dist/charts/XYChart.js.map +1 -1
  44. package/dist/charts/axis-ticks.d.ts +1 -1
  45. package/dist/charts/axis-ticks.js +4 -5
  46. package/dist/charts/axis-ticks.js.map +1 -1
  47. package/dist/charts/flow.d.ts +4 -11
  48. package/dist/charts/flow.js +4 -4
  49. package/dist/charts/flow.js.map +1 -1
  50. package/dist/charts/frame.d.ts +6 -30
  51. package/dist/charts/frame.js +6 -99
  52. package/dist/charts/frame.js.map +1 -1
  53. package/dist/charts/geo/projection.d.ts +45 -0
  54. package/dist/charts/geo/projection.js +201 -0
  55. package/dist/charts/geo/projection.js.map +1 -0
  56. package/dist/charts/geo/topojson.d.ts +50 -0
  57. package/dist/charts/geo/topojson.js +119 -0
  58. package/dist/charts/geo/topojson.js.map +1 -0
  59. package/dist/charts/index.d.ts +21 -9
  60. package/dist/charts/index.js +19 -8
  61. package/dist/charts/label-layout.js.map +1 -1
  62. package/dist/charts/layout/chord.d.ts +44 -0
  63. package/dist/charts/layout/chord.js +45 -0
  64. package/dist/charts/layout/chord.js.map +1 -0
  65. package/dist/charts/layout/graph.d.ts +49 -0
  66. package/dist/charts/layout/graph.js +268 -0
  67. package/dist/charts/layout/graph.js.map +1 -0
  68. package/dist/charts/layout/sankey.d.ts +79 -0
  69. package/dist/charts/layout/sankey.js +200 -0
  70. package/dist/charts/layout/sankey.js.map +1 -0
  71. package/dist/charts/layout/treemap.d.ts +46 -0
  72. package/dist/charts/layout/treemap.js +152 -0
  73. package/dist/charts/layout/treemap.js.map +1 -0
  74. package/dist/charts/marks.d.ts +79 -0
  75. package/dist/charts/marks.js +231 -0
  76. package/dist/charts/marks.js.map +1 -0
  77. package/dist/charts/plot.d.ts +107 -0
  78. package/dist/charts/plot.js +231 -0
  79. package/dist/charts/plot.js.map +1 -0
  80. package/dist/charts/scale.d.ts +29 -0
  81. package/dist/charts/scale.js +244 -0
  82. package/dist/charts/scale.js.map +1 -0
  83. package/dist/charts/shape.d.ts +46 -0
  84. package/dist/charts/shape.js +131 -0
  85. package/dist/charts/shape.js.map +1 -0
  86. package/dist/charts/stack.d.ts +17 -0
  87. package/dist/charts/stack.js +35 -0
  88. package/dist/charts/stack.js.map +1 -0
  89. package/dist/charts/text-size.d.ts +12 -0
  90. package/dist/charts/text-size.js +32 -0
  91. package/dist/charts/text-size.js.map +1 -0
  92. package/dist/maps/china-provinces.js +35680 -0
  93. package/dist/maps/china-provinces.js.map +1 -0
  94. package/dist/maps/china.d.ts +13 -0
  95. package/dist/maps/china.js +8 -0
  96. package/dist/maps/china.js.map +1 -0
  97. package/dist/maps/index.d.ts +9 -0
  98. package/dist/maps/index.js +3 -0
  99. package/dist/maps/world-countries.js +22273 -0
  100. package/dist/maps/world-countries.js.map +1 -0
  101. package/dist/maps/world.d.ts +13 -0
  102. package/dist/maps/world.js +8 -0
  103. package/dist/maps/world.js.map +1 -0
  104. package/dist/overlay/detached.js.map +1 -1
  105. package/package.json +7 -8
  106. package/dist/charts/single.d.ts +0 -41
  107. package/dist/charts/single.js +0 -66
  108. package/dist/charts/single.js.map +0 -1
@@ -0,0 +1,46 @@
1
+ /** 一个点 [x, y] */
2
+ export type ChartPoint = readonly [number, number];
3
+ /** 线的形状 */
4
+ export interface LineCurves {
5
+ /** 折线:相邻的点直线相连(默认) */
6
+ linear: unknown;
7
+ /** 平滑曲线:不会越过数据点(单调插值),趋势更柔和 */
8
+ monotone: unknown;
9
+ /** 阶梯:值保持到下一个点才跳变,适合离散的状态、价格档位 */
10
+ step: unknown;
11
+ }
12
+ /**
13
+ * 一串点连成的路径;start 是开头的命令(M 新起一段,L 接着上一段画:面积的下沿)。
14
+ * 少于三个点时平滑曲线退化成直线
15
+ */
16
+ export declare function linePath(points: readonly ChartPoint[], curve?: keyof LineCurves, start?: 'M' | 'L'): string;
17
+ /** 面积:上沿 top 从左到右,下沿 bottom(与 top 一一对应)从右到左,同一种曲线,闭合 */
18
+ export declare function areaPath(top: readonly ChartPoint[], bottom: readonly ChartPoint[], curve?: keyof LineCurves): string;
19
+ /** 柱子的哪一端是圆角:柱顶朝哪个方向 */
20
+ export type BarEnd = 'top' | 'bottom' | 'left' | 'right' | 'none';
21
+ /** 柱子:矩形(左上角 x、y,宽高),end 那一端的两个角是半径 radius 的圆角(不超过宽或高的一半) */
22
+ export declare function barPath(x: number, y: number, width: number, height: number, radius: number, end: BarEnd): string;
23
+ /** 环形的一段:角度从 12 点钟方向顺时针(弧度),圆心在原点 */
24
+ export interface ArcShape {
25
+ /** 内半径;0 是饼图的扇形 */
26
+ inner: number;
27
+ /** 外半径 */
28
+ outer: number;
29
+ /** 起始角 */
30
+ start: number;
31
+ /** 结束角 */
32
+ end: number;
33
+ /** 四个角的圆角半径,默认 0 */
34
+ corner?: number;
35
+ }
36
+ /** 半径 r、角度 angle(12 点钟方向顺时针)处的点 */
37
+ export declare function polarPoint(r: number, angle: number): [number, number];
38
+ /**
39
+ * 环形一段的路径:两条径向的边、内外两段弧;corner 时四个角各是一段与边、弧都相切的小圆弧
40
+ * (边是径向的,与圆正交,切点可以直接算出)。整圈时画成两段弧(没有边)
41
+ */
42
+ export declare function arcPath({ inner, outer, start, end, corner }: ArcShape): string;
43
+ /** 弦图的一根弦:两端是圆上的两段弧(半径 radius,角度同 arcPath),中间经圆心的二次曲线相连(同 d3 的 ribbon) */
44
+ export declare function ribbonPath(radius: number, source: readonly [number, number], target: readonly [number, number]): string;
45
+ /** 横向的流向带(桑基图的连线):从 (x0, y0) 到 (x1, y1) 的 S 形三次曲线,控制点在两端的中间 */
46
+ export declare function horizontalLinkPath(x0: number, y0: number, x1: number, y1: number): string;
@@ -0,0 +1,131 @@
1
+ import { svgNumber } from "../utils/data/number.js";
2
+ //#region src/charts/shape.ts
3
+ /**
4
+ * 图形的 SVG 路径:折线与面积(直线、单调平滑、阶梯)、一端圆角的柱子、环形的扇区、弦图的弦、桑基图的带子。
5
+ * 曲线的算法同 d3-shape(curveMonotoneX 是 Steffen 的单调三次插值,不会越过数据点),写成只产出路径字符串的精简版。
6
+ * 坐标保留三位小数(svgNumber):服务端与浏览器算出的路径一致。
7
+ *
8
+ * linePath([[0, 10], [40, 30], [80, 20]], 'monotone') // 'M0,10C13.333,…'
9
+ * areaPath(top, bottom, 'linear') // 上沿从左到右、下沿从右到左,闭合
10
+ * arcPath({ inner: 60, outer: 88, start: 0, end: Math.PI / 2, corner: 3 })
11
+ */
12
+ /** 两个数字写成“x,y” */
13
+ var pair = (x, y) => `${svgNumber(x)},${svgNumber(y)}`;
14
+ var sign = (value) => value < 0 ? -1 : 1;
15
+ /** 中间一点的切线斜率:两侧的斜率异号时为 0(极值点不越过),否则取不超过两侧的调和值(同 d3 的 slope3) */
16
+ function interiorSlope(a, b, c) {
17
+ const h0 = b[0] - a[0];
18
+ const h1 = c[0] - b[0];
19
+ const s0 = (b[1] - a[1]) / (h0 || (h1 < 0 ? -0 : 0));
20
+ const s1 = (c[1] - b[1]) / (h1 || (h0 < 0 ? -0 : 0));
21
+ const p = (s0 * h1 + s1 * h0) / (h0 + h1);
22
+ return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), .5 * Math.abs(p)) || 0;
23
+ }
24
+ /** 端点的切线斜率:由相邻一段的斜率与相邻点的切线推出(同 d3 的 slope2) */
25
+ function endSlope(a, b, tangent) {
26
+ const h = b[0] - a[0];
27
+ return h ? (3 * (b[1] - a[1]) / h - tangent) / 2 : tangent;
28
+ }
29
+ /** 单调三次插值:各点的切线,再按 Hermite 写成三次贝塞尔 */
30
+ function monotoneCommands(points) {
31
+ const n = points.length;
32
+ const tangents = points.map((point, i) => i > 0 && i < n - 1 ? interiorSlope(points[i - 1], point, points[i + 1]) : 0);
33
+ tangents[0] = endSlope(points[0], points[1], tangents[1]);
34
+ tangents[n - 1] = endSlope(points[n - 2], points[n - 1], tangents[n - 2]);
35
+ let path = "";
36
+ for (let i = 1; i < n; i += 1) {
37
+ const [x0, y0] = points[i - 1];
38
+ const [x1, y1] = points[i];
39
+ const dx = (x1 - x0) / 3;
40
+ path += `C${pair(x0 + dx, y0 + dx * tangents[i - 1])},${pair(x1 - dx, y1 - dx * tangents[i])},${pair(x1, y1)}`;
41
+ }
42
+ return path;
43
+ }
44
+ /**
45
+ * 一串点连成的路径;start 是开头的命令(M 新起一段,L 接着上一段画:面积的下沿)。
46
+ * 少于三个点时平滑曲线退化成直线
47
+ */
48
+ function linePath(points, curve = "linear", start = "M") {
49
+ if (points.length === 0) return "";
50
+ const [first, ...rest] = points;
51
+ let path = `${start}${pair(first[0], first[1])}`;
52
+ if (curve === "monotone" && points.length > 2) return path + monotoneCommands(points);
53
+ let previous = first;
54
+ for (const point of rest) {
55
+ if (curve === "step") path += `L${pair(point[0], previous[1])}`;
56
+ path += `L${pair(point[0], point[1])}`;
57
+ previous = point;
58
+ }
59
+ return path;
60
+ }
61
+ /** 面积:上沿 top 从左到右,下沿 bottom(与 top 一一对应)从右到左,同一种曲线,闭合 */
62
+ function areaPath(top, bottom, curve = "linear") {
63
+ if (top.length === 0) return "";
64
+ const back = curve === "step" ? bottom.flatMap((point, i) => i === 0 ? [point] : [[point[0], bottom[i - 1][1]], point]) : bottom;
65
+ return `${linePath(top, curve)}${linePath([...back].reverse(), curve === "step" ? "linear" : curve, "L")}Z`;
66
+ }
67
+ /** 柱子:矩形(左上角 x、y,宽高),end 那一端的两个角是半径 radius 的圆角(不超过宽或高的一半) */
68
+ function barPath(x, y, width, height, radius, end) {
69
+ const w = Math.max(width, 0);
70
+ const h = Math.max(height, 0);
71
+ const vertical = end === "top" || end === "bottom";
72
+ const r = end === "none" ? 0 : Math.max(0, Math.min(radius, vertical ? w / 2 : h / 2, vertical ? h : w));
73
+ const [x1, y1] = [x + w, y + h];
74
+ const corner = (cx, cy) => `A${pair(r, r)},0,0,1,${pair(cx, cy)}`;
75
+ if (!r) return `M${pair(x, y)}H${svgNumber(x1)}V${svgNumber(y1)}H${svgNumber(x)}Z`;
76
+ if (end === "top") return `M${pair(x, y1)}V${svgNumber(y + r)}${corner(x + r, y)}H${svgNumber(x1 - r)}${corner(x1, y + r)}V${svgNumber(y1)}Z`;
77
+ if (end === "bottom") return `M${pair(x1, y)}V${svgNumber(y1 - r)}${corner(x1 - r, y1)}H${svgNumber(x + r)}${corner(x, y1 - r)}V${svgNumber(y)}Z`;
78
+ if (end === "right") return `M${pair(x, y)}H${svgNumber(x1 - r)}${corner(x1, y + r)}V${svgNumber(y1 - r)}${corner(x1 - r, y1)}H${svgNumber(x)}Z`;
79
+ return `M${pair(x1, y1)}H${svgNumber(x + r)}${corner(x, y1 - r)}V${svgNumber(y + r)}${corner(x + r, y)}H${svgNumber(x1)}Z`;
80
+ }
81
+ /** 半径 r、角度 angle(12 点钟方向顺时针)处的点 */
82
+ function polarPoint(r, angle) {
83
+ return [r * Math.sin(angle), -r * Math.cos(angle)];
84
+ }
85
+ /**
86
+ * 环形一段的路径:两条径向的边、内外两段弧;corner 时四个角各是一段与边、弧都相切的小圆弧
87
+ * (边是径向的,与圆正交,切点可以直接算出)。整圈时画成两段弧(没有边)
88
+ */
89
+ function arcPath({ inner, outer, start, end, corner = 0 }) {
90
+ const sweep = end - start;
91
+ if (!(sweep > 0) || !(outer > 0)) return "";
92
+ const at = (r, angle) => pair(...polarPoint(r, angle));
93
+ const arc = (r, to, clockwise, span) => `A${pair(r, r)},0,${span > Math.PI ? 1 : 0},${clockwise ? 1 : 0},${at(r, to)}`;
94
+ if (sweep >= Math.PI * 2 - 1e-9) {
95
+ const outerRing = `M${at(outer, 0)}${arc(outer, Math.PI, true, Math.PI)}${arc(outer, 0, true, Math.PI)}Z`;
96
+ if (inner <= 0) return outerRing;
97
+ return `${outerRing}M${at(inner, 0)}${arc(inner, Math.PI, false, Math.PI)}${arc(inner, 0, false, Math.PI)}Z`;
98
+ }
99
+ const r = Math.max(0, Math.min(corner, (outer - inner) / 2, (inner > 0 ? inner : outer) * sweep / 2.2));
100
+ if (r < .5) {
101
+ const outerPart = `M${at(outer, start)}${arc(outer, end, true, sweep)}`;
102
+ if (inner <= 0) return `${outerPart}L0,0Z`;
103
+ return `${outerPart}L${at(inner, end)}${arc(inner, start, false, sweep)}Z`;
104
+ }
105
+ const outerShift = Math.asin(r / (outer - r));
106
+ const outerEdge = Math.sqrt((outer - r) ** 2 - r * r);
107
+ const fillet = (to) => `A${pair(r, r)},0,0,1,${to}`;
108
+ let path = `M${at(outerEdge, start)}${fillet(at(outer, start + outerShift))}${arc(outer, end - outerShift, true, sweep - outerShift * 2)}${fillet(at(outerEdge, end))}`;
109
+ if (inner <= 0) return `${path}L0,0Z`;
110
+ const innerShift = Math.asin(r / (inner + r));
111
+ const innerEdge = Math.sqrt((inner + r) ** 2 - r * r);
112
+ path += `L${at(innerEdge, end)}${fillet(at(inner, end - innerShift))}${arc(inner, start + innerShift, false, sweep - innerShift * 2)}${fillet(at(innerEdge, start))}Z`;
113
+ return path;
114
+ }
115
+ /** 弦图的一根弦:两端是圆上的两段弧(半径 radius,角度同 arcPath),中间经圆心的二次曲线相连(同 d3 的 ribbon) */
116
+ function ribbonPath(radius, source, target) {
117
+ const at = (angle) => pair(...polarPoint(radius, angle));
118
+ const arc = ([from, to]) => `A${pair(radius, radius)},0,${to - from > Math.PI ? 1 : 0},1,${at(to)}`;
119
+ let path = `M${at(source[0])}${arc(source)}`;
120
+ if (source[0] !== target[0] || source[1] !== target[1]) path += `Q0,0,${at(target[0])}${arc(target)}`;
121
+ return `${path}Q0,0,${at(source[0])}Z`;
122
+ }
123
+ /** 横向的流向带(桑基图的连线):从 (x0, y0) 到 (x1, y1) 的 S 形三次曲线,控制点在两端的中间 */
124
+ function horizontalLinkPath(x0, y0, x1, y1) {
125
+ const middle = (x0 + x1) / 2;
126
+ return `M${pair(x0, y0)}C${pair(middle, y0)},${pair(middle, y1)},${pair(x1, y1)}`;
127
+ }
128
+ //#endregion
129
+ export { arcPath, areaPath, barPath, horizontalLinkPath, linePath, polarPoint, ribbonPath };
130
+
131
+ //# sourceMappingURL=shape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.js","names":[],"sources":["../../src/charts/shape.ts"],"sourcesContent":["/**\n * 图形的 SVG 路径:折线与面积(直线、单调平滑、阶梯)、一端圆角的柱子、环形的扇区、弦图的弦、桑基图的带子。\n * 曲线的算法同 d3-shape(curveMonotoneX 是 Steffen 的单调三次插值,不会越过数据点),写成只产出路径字符串的精简版。\n * 坐标保留三位小数(svgNumber):服务端与浏览器算出的路径一致。\n *\n * linePath([[0, 10], [40, 30], [80, 20]], 'monotone') // 'M0,10C13.333,…'\n * areaPath(top, bottom, 'linear') // 上沿从左到右、下沿从右到左,闭合\n * arcPath({ inner: 60, outer: 88, start: 0, end: Math.PI / 2, corner: 3 })\n */\nimport { svgNumber } from '../utils/data/number';\n\n/** 一个点 [x, y] */\nexport type ChartPoint = readonly [number, number];\n\n/** 线的形状 */\nexport interface LineCurves {\n /** 折线:相邻的点直线相连(默认) */\n linear: unknown;\n /** 平滑曲线:不会越过数据点(单调插值),趋势更柔和 */\n monotone: unknown;\n /** 阶梯:值保持到下一个点才跳变,适合离散的状态、价格档位 */\n step: unknown;\n}\n\n/** 两个数字写成“x,y” */\nconst pair = (x: number, y: number) => `${svgNumber(x)},${svgNumber(y)}`;\n\nconst sign = (value: number) => (value < 0 ? -1 : 1);\n\n/** 中间一点的切线斜率:两侧的斜率异号时为 0(极值点不越过),否则取不超过两侧的调和值(同 d3 的 slope3) */\nfunction interiorSlope(a: ChartPoint, b: ChartPoint, c: ChartPoint): number {\n const h0 = b[0] - a[0];\n const h1 = c[0] - b[0];\n // 横坐标相同时除以带符号的 0:得到同向的无穷大,下面取 min 时自然被别的值替代\n const s0 = (b[1] - a[1]) / (h0 || (h1 < 0 ? -0 : 0));\n const s1 = (c[1] - b[1]) / (h1 || (h0 < 0 ? -0 : 0));\n const p = (s0 * h1 + s1 * h0) / (h0 + h1);\n return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;\n}\n\n/** 端点的切线斜率:由相邻一段的斜率与相邻点的切线推出(同 d3 的 slope2) */\nfunction endSlope(a: ChartPoint, b: ChartPoint, tangent: number): number {\n const h = b[0] - a[0];\n return h ? ((3 * (b[1] - a[1])) / h - tangent) / 2 : tangent;\n}\n\n/** 单调三次插值:各点的切线,再按 Hermite 写成三次贝塞尔 */\nfunction monotoneCommands(points: readonly ChartPoint[]): string {\n const n = points.length;\n const tangents = points.map((point, i) =>\n i > 0 && i < n - 1 ? interiorSlope(points[i - 1]!, point, points[i + 1]!) : 0,\n );\n tangents[0] = endSlope(points[0]!, points[1]!, tangents[1]!);\n tangents[n - 1] = endSlope(points[n - 2]!, points[n - 1]!, tangents[n - 2]!);\n let path = '';\n for (let i = 1; i < n; i += 1) {\n const [x0, y0] = points[i - 1]!;\n const [x1, y1] = points[i]!;\n const dx = (x1 - x0) / 3;\n path += `C${pair(x0 + dx, y0 + dx * tangents[i - 1]!)},${pair(x1 - dx, y1 - dx * tangents[i]!)},${pair(x1, y1)}`;\n }\n return path;\n}\n\n/**\n * 一串点连成的路径;start 是开头的命令(M 新起一段,L 接着上一段画:面积的下沿)。\n * 少于三个点时平滑曲线退化成直线\n */\nexport function linePath(\n points: readonly ChartPoint[],\n curve: keyof LineCurves = 'linear',\n start: 'M' | 'L' = 'M',\n): string {\n if (points.length === 0) return '';\n const [first, ...rest] = points;\n let path = `${start}${pair(first![0], first![1])}`;\n if (curve === 'monotone' && points.length > 2) return path + monotoneCommands(points);\n let previous = first!;\n for (const point of rest) {\n // 阶梯:横着走到下一个点的横坐标,再竖着跳到它的值\n if (curve === 'step') path += `L${pair(point[0], previous[1])}`;\n path += `L${pair(point[0], point[1])}`;\n previous = point;\n }\n return path;\n}\n\n/** 面积:上沿 top 从左到右,下沿 bottom(与 top 一一对应)从右到左,同一种曲线,闭合 */\nexport function areaPath(\n top: readonly ChartPoint[],\n bottom: readonly ChartPoint[],\n curve: keyof LineCurves = 'linear',\n): string {\n if (top.length === 0) return '';\n // 阶梯的下沿倒着画时要先竖后横,才与上沿的拐角对齐:倒着画的阶梯把每一步的值挪到前一个点\n const back =\n curve === 'step'\n ? bottom.flatMap((point, i) =>\n i === 0 ? [point] : [[point[0], bottom[i - 1]![1]] as const, point],\n )\n : bottom;\n return `${linePath(top, curve)}${linePath([...back].reverse(), curve === 'step' ? 'linear' : curve, 'L')}Z`;\n}\n\n/** 柱子的哪一端是圆角:柱顶朝哪个方向 */\nexport type BarEnd = 'top' | 'bottom' | 'left' | 'right' | 'none';\n\n/** 柱子:矩形(左上角 x、y,宽高),end 那一端的两个角是半径 radius 的圆角(不超过宽或高的一半) */\nexport function barPath(\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number,\n end: BarEnd,\n): string {\n const w = Math.max(width, 0);\n const h = Math.max(height, 0);\n const vertical = end === 'top' || end === 'bottom';\n const r =\n end === 'none' ? 0 : Math.max(0, Math.min(radius, vertical ? w / 2 : h / 2, vertical ? h : w));\n const [x1, y1] = [x + w, y + h];\n const corner = (cx: number, cy: number) => `A${pair(r, r)},0,0,1,${pair(cx, cy)}`;\n if (!r) return `M${pair(x, y)}H${svgNumber(x1)}V${svgNumber(y1)}H${svgNumber(x)}Z`;\n if (end === 'top')\n return `M${pair(x, y1)}V${svgNumber(y + r)}${corner(x + r, y)}H${svgNumber(x1 - r)}${corner(x1, y + r)}V${svgNumber(y1)}Z`;\n if (end === 'bottom')\n return `M${pair(x1, y)}V${svgNumber(y1 - r)}${corner(x1 - r, y1)}H${svgNumber(x + r)}${corner(x, y1 - r)}V${svgNumber(y)}Z`;\n if (end === 'right')\n return `M${pair(x, y)}H${svgNumber(x1 - r)}${corner(x1, y + r)}V${svgNumber(y1 - r)}${corner(x1 - r, y1)}H${svgNumber(x)}Z`;\n return `M${pair(x1, y1)}H${svgNumber(x + r)}${corner(x, y1 - r)}V${svgNumber(y + r)}${corner(x + r, y)}H${svgNumber(x1)}Z`;\n}\n\n/** 环形的一段:角度从 12 点钟方向顺时针(弧度),圆心在原点 */\nexport interface ArcShape {\n /** 内半径;0 是饼图的扇形 */\n inner: number;\n /** 外半径 */\n outer: number;\n /** 起始角 */\n start: number;\n /** 结束角 */\n end: number;\n /** 四个角的圆角半径,默认 0 */\n corner?: number;\n}\n\n/** 半径 r、角度 angle(12 点钟方向顺时针)处的点 */\nexport function polarPoint(r: number, angle: number): [number, number] {\n return [r * Math.sin(angle), -r * Math.cos(angle)];\n}\n\n/**\n * 环形一段的路径:两条径向的边、内外两段弧;corner 时四个角各是一段与边、弧都相切的小圆弧\n * (边是径向的,与圆正交,切点可以直接算出)。整圈时画成两段弧(没有边)\n */\nexport function arcPath({ inner, outer, start, end, corner = 0 }: ArcShape): string {\n const sweep = end - start;\n if (!(sweep > 0) || !(outer > 0)) return '';\n const at = (r: number, angle: number) => pair(...polarPoint(r, angle));\n const arc = (r: number, to: number, clockwise: boolean, span: number) =>\n `A${pair(r, r)},0,${span > Math.PI ? 1 : 0},${clockwise ? 1 : 0},${at(r, to)}`;\n if (sweep >= Math.PI * 2 - 1e-9) {\n const outerRing = `M${at(outer, 0)}${arc(outer, Math.PI, true, Math.PI)}${arc(outer, 0, true, Math.PI)}Z`;\n if (inner <= 0) return outerRing;\n return `${outerRing}M${at(inner, 0)}${arc(inner, Math.PI, false, Math.PI)}${arc(inner, 0, false, Math.PI)}Z`;\n }\n // 圆角不超过环宽的一半,也不超过这一段在内(饼图是外)弧上长度的一半\n const r = Math.max(\n 0,\n Math.min(corner, (outer - inner) / 2, ((inner > 0 ? inner : outer) * sweep) / 2.2),\n );\n if (r < 0.5) {\n const outerPart = `M${at(outer, start)}${arc(outer, end, true, sweep)}`;\n if (inner <= 0) return `${outerPart}L0,0Z`;\n return `${outerPart}L${at(inner, end)}${arc(inner, start, false, sweep)}Z`;\n }\n // 外角:小圆心在半径 outer - r 上,切边的点离圆心 √((outer-r)² - r²),切弧的点偏开 asin(r / (outer - r))\n const outerShift = Math.asin(r / (outer - r));\n const outerEdge = Math.sqrt((outer - r) ** 2 - r * r);\n const fillet = (to: string) => `A${pair(r, r)},0,0,1,${to}`;\n let path =\n `M${at(outerEdge, start)}${fillet(at(outer, start + outerShift))}` +\n `${arc(outer, end - outerShift, true, sweep - outerShift * 2)}${fillet(at(outerEdge, end))}`;\n if (inner <= 0) return `${path}L0,0Z`;\n // 内角:小圆心在半径 inner + r 上\n const innerShift = Math.asin(r / (inner + r));\n const innerEdge = Math.sqrt((inner + r) ** 2 - r * r);\n path +=\n `L${at(innerEdge, end)}${fillet(at(inner, end - innerShift))}` +\n `${arc(inner, start + innerShift, false, sweep - innerShift * 2)}${fillet(at(innerEdge, start))}Z`;\n return path;\n}\n\n/** 弦图的一根弦:两端是圆上的两段弧(半径 radius,角度同 arcPath),中间经圆心的二次曲线相连(同 d3 的 ribbon) */\nexport function ribbonPath(\n radius: number,\n source: readonly [number, number],\n target: readonly [number, number],\n): string {\n const at = (angle: number) => pair(...polarPoint(radius, angle));\n const arc = ([from, to]: readonly [number, number]) =>\n `A${pair(radius, radius)},0,${to - from > Math.PI ? 1 : 0},1,${at(to)}`;\n let path = `M${at(source[0])}${arc(source)}`;\n if (source[0] !== target[0] || source[1] !== target[1])\n path += `Q0,0,${at(target[0])}${arc(target)}`;\n return `${path}Q0,0,${at(source[0])}Z`;\n}\n\n/** 横向的流向带(桑基图的连线):从 (x0, y0) 到 (x1, y1) 的 S 形三次曲线,控制点在两端的中间 */\nexport function horizontalLinkPath(x0: number, y0: number, x1: number, y1: number): string {\n const middle = (x0 + x1) / 2;\n return `M${pair(x0, y0)}C${pair(middle, y0)},${pair(middle, y1)},${pair(x1, y1)}`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 堆叠:各系列在同一类目上依次叠起,正值从 0 往上叠、负值从 0 往下叠(同 d3 的 stackOffsetDiverging)。
3
+ * 柱状图、面积图、组合图的堆叠与十字线圆点、标注圈的位置共用。
4
+ *
5
+ * stackValues([[3, 5], [2, -1]]) // 系列 0:[[0,3], [0,5]];系列 1:[[3,5], [-1,0]]
6
+ */
7
+ /** 一个系列在一行上叠出的一段 */
8
+ export interface StackSegment {
9
+ /** 下沿(负值是靠近 0 的一端以外的那端) */
10
+ low: number;
11
+ /** 上沿 */
12
+ high: number;
13
+ /** 原值;空值是 undefined,这时 low、high 都在当前的正向累计处(高度为 0,面积连续) */
14
+ value: number | undefined;
15
+ }
16
+ /** values[系列][行] → 每个系列在每一行的一段 */
17
+ export declare function stackValues(values: readonly (readonly (number | undefined)[])[]): StackSegment[][];
@@ -0,0 +1,35 @@
1
+ //#region src/charts/stack.ts
2
+ /** values[系列][行] → 每个系列在每一行的一段 */
3
+ function stackValues(values) {
4
+ const rows = Math.max(0, ...values.map((list) => list.length));
5
+ const positive = Array.from({ length: rows }, () => 0);
6
+ const negative = Array.from({ length: rows }, () => 0);
7
+ return values.map((list) => Array.from({ length: rows }, (_, row) => {
8
+ const value = list[row];
9
+ if (value === void 0 || !Number.isFinite(value)) return {
10
+ low: positive[row],
11
+ high: positive[row],
12
+ value: void 0
13
+ };
14
+ if (value >= 0) {
15
+ const low = positive[row];
16
+ positive[row] = low + value;
17
+ return {
18
+ low,
19
+ high: low + value,
20
+ value
21
+ };
22
+ }
23
+ const high = negative[row];
24
+ negative[row] = high + value;
25
+ return {
26
+ low: high + value,
27
+ high,
28
+ value
29
+ };
30
+ }));
31
+ }
32
+ //#endregion
33
+ export { stackValues };
34
+
35
+ //# sourceMappingURL=stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack.js","names":[],"sources":["../../src/charts/stack.ts"],"sourcesContent":["/**\n * 堆叠:各系列在同一类目上依次叠起,正值从 0 往上叠、负值从 0 往下叠(同 d3 的 stackOffsetDiverging)。\n * 柱状图、面积图、组合图的堆叠与十字线圆点、标注圈的位置共用。\n *\n * stackValues([[3, 5], [2, -1]]) // 系列 0:[[0,3], [0,5]];系列 1:[[3,5], [-1,0]]\n */\n\n/** 一个系列在一行上叠出的一段 */\nexport interface StackSegment {\n /** 下沿(负值是靠近 0 的一端以外的那端) */\n low: number;\n /** 上沿 */\n high: number;\n /** 原值;空值是 undefined,这时 low、high 都在当前的正向累计处(高度为 0,面积连续) */\n value: number | undefined;\n}\n\n/** values[系列][行] → 每个系列在每一行的一段 */\nexport function stackValues(\n values: readonly (readonly (number | undefined)[])[],\n): StackSegment[][] {\n const rows = Math.max(0, ...values.map((list) => list.length));\n const positive = Array.from({ length: rows }, () => 0);\n const negative = Array.from({ length: rows }, () => 0);\n return values.map((list) =>\n Array.from({ length: rows }, (_, row) => {\n const value = list[row];\n if (value === undefined || !Number.isFinite(value))\n return { low: positive[row]!, high: positive[row]!, value: undefined };\n if (value >= 0) {\n const low = positive[row]!;\n positive[row] = low + value;\n return { low, high: low + value, value };\n }\n const high = negative[row]!;\n negative[row] = high + value;\n return { low: high + value, high, value };\n }),\n );\n}\n"],"mappings":";;AAkBA,SAAgB,YACd,QACkB;CAClB,MAAM,OAAO,KAAK,IAAI,GAAG,GAAG,OAAO,KAAK,SAAS,KAAK,MAAM,CAAC;CAC7D,MAAM,WAAW,MAAM,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC;CACrD,MAAM,WAAW,MAAM,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC;CACrD,OAAO,OAAO,KAAK,SACjB,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,QAAQ;EACvC,MAAM,QAAQ,KAAK;EACnB,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,SAAS,KAAK,GAC/C,OAAO;GAAE,KAAK,SAAS;GAAO,MAAM,SAAS;GAAO,OAAO,KAAA;EAAU;EACvE,IAAI,SAAS,GAAG;GACd,MAAM,MAAM,SAAS;GACrB,SAAS,OAAO,MAAM;GACtB,OAAO;IAAE;IAAK,MAAM,MAAM;IAAO;GAAM;EACzC;EACA,MAAM,OAAO,SAAS;EACtB,SAAS,OAAO,OAAO;EACvB,OAAO;GAAE,KAAK,OAAO;GAAO;GAAM;EAAM;CAC1C,CAAC,CACH;AACF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 图表里文字的宽度估算:留坐标轴的边距、决定类目刻度隔几个写一个、地点名字的避让都要在画之前知道文字多宽。
3
+ * 不去量 DOM(服务端渲染、还没挂上时也要算):中日韩文字、全角符号按一个字号宽,其余按 0.6 个字号宽,
4
+ * 宁宽勿窄(宽了只是多留一点空,窄了会叠在一起)。
5
+ *
6
+ * estimateTextWidth('华东区 2026', 12) // 3 × 12 + 5 × 7.2 = 72
7
+ * truncateText('很长很长的类目名', 60, 12) // '很长很长…'
8
+ */
9
+ /** 估算文字的宽度(px);fontSize 是字号(px),默认 12(主题的 xs) */
10
+ export declare function estimateTextWidth(text: string, fontSize?: number): number;
11
+ /** 文字超过 maxWidth 时截短并加省略号;放得下时原样返回 */
12
+ export declare function truncateText(text: string, maxWidth: number, fontSize?: number): string;
@@ -0,0 +1,32 @@
1
+ //#region src/charts/text-size.ts
2
+ /**
3
+ * 图表里文字的宽度估算:留坐标轴的边距、决定类目刻度隔几个写一个、地点名字的避让都要在画之前知道文字多宽。
4
+ * 不去量 DOM(服务端渲染、还没挂上时也要算):中日韩文字、全角符号按一个字号宽,其余按 0.6 个字号宽,
5
+ * 宁宽勿窄(宽了只是多留一点空,窄了会叠在一起)。
6
+ *
7
+ * estimateTextWidth('华东区 2026', 12) // 3 × 12 + 5 × 7.2 = 72
8
+ * truncateText('很长很长的类目名', 60, 12) // '很长很长…'
9
+ */
10
+ /** 按一个字号宽算的字:中日韩文字、全角标点、假名、谚文 */
11
+ var WIDE = /[ᄀ-ᅟ⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/u;
12
+ /** 估算文字的宽度(px);fontSize 是字号(px),默认 12(主题的 xs) */
13
+ function estimateTextWidth(text, fontSize = 12) {
14
+ let width = 0;
15
+ for (const char of text) width += WIDE.test(char) ? fontSize : fontSize * .6;
16
+ return width;
17
+ }
18
+ /** 文字超过 maxWidth 时截短并加省略号;放得下时原样返回 */
19
+ function truncateText(text, maxWidth, fontSize = 12) {
20
+ if (estimateTextWidth(text, fontSize) <= maxWidth) return text;
21
+ const room = maxWidth - fontSize;
22
+ let result = "";
23
+ for (const char of text) {
24
+ if (estimateTextWidth(result + char, fontSize) > room) break;
25
+ result += char;
26
+ }
27
+ return `${result}…`;
28
+ }
29
+ //#endregion
30
+ export { estimateTextWidth, truncateText };
31
+
32
+ //# sourceMappingURL=text-size.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-size.js","names":[],"sources":["../../src/charts/text-size.ts"],"sourcesContent":["/**\n * 图表里文字的宽度估算:留坐标轴的边距、决定类目刻度隔几个写一个、地点名字的避让都要在画之前知道文字多宽。\n * 不去量 DOM(服务端渲染、还没挂上时也要算):中日韩文字、全角符号按一个字号宽,其余按 0.6 个字号宽,\n * 宁宽勿窄(宽了只是多留一点空,窄了会叠在一起)。\n *\n * estimateTextWidth('华东区 2026', 12) // 3 × 12 + 5 × 7.2 = 72\n * truncateText('很长很长的类目名', 60, 12) // '很长很长…'\n */\n\n/** 按一个字号宽算的字:中日韩文字、全角标点、假名、谚文 */\nconst WIDE = /[ᄀ-ᅟ⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/u;\n\n/** 估算文字的宽度(px);fontSize 是字号(px),默认 12(主题的 xs) */\nexport function estimateTextWidth(text: string, fontSize = 12): number {\n let width = 0;\n for (const char of text) width += WIDE.test(char) ? fontSize : fontSize * 0.6;\n return width;\n}\n\n/** 文字超过 maxWidth 时截短并加省略号;放得下时原样返回 */\nexport function truncateText(text: string, maxWidth: number, fontSize = 12): string {\n if (estimateTextWidth(text, fontSize) <= maxWidth) return text;\n const room = maxWidth - fontSize;\n let result = '';\n for (const char of text) {\n if (estimateTextWidth(result + char, fontSize) > room) break;\n result += char;\n }\n return `${result}…`;\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAM,OAAO;;AAGb,SAAgB,kBAAkB,MAAc,WAAW,IAAY;CACrE,IAAI,QAAQ;CACZ,KAAK,MAAM,QAAQ,MAAM,SAAS,KAAK,KAAK,IAAI,IAAI,WAAW,WAAW;CAC1E,OAAO;AACT;;AAGA,SAAgB,aAAa,MAAc,UAAkB,WAAW,IAAY;CAClF,IAAI,kBAAkB,MAAM,QAAQ,KAAK,UAAU,OAAO;CAC1D,MAAM,OAAO,WAAW;CACxB,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,MAAM;EACvB,IAAI,kBAAkB,SAAS,MAAM,QAAQ,IAAI,MAAM;EACvD,UAAU;CACZ;CACA,OAAO,GAAG,OAAO;AACnB"}