@dou-ui/chart 0.0.0-stage → 0.1.0-alpha.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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/chart.js +6 -0
  4. package/dist/chart.js.map +1 -0
  5. package/dist/chart.vue_vue_type_script_setup_true_lang.js +4245 -0
  6. package/dist/chart.vue_vue_type_script_setup_true_lang.js.map +1 -0
  7. package/dist/components/area.js +6 -0
  8. package/dist/components/area.js.map +1 -0
  9. package/dist/components/area.vue_vue_type_script_setup_true_lang.js +55 -0
  10. package/dist/components/area.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/components/axis.js +6 -0
  12. package/dist/components/axis.js.map +1 -0
  13. package/dist/components/axis.vue_vue_type_script_setup_true_lang.js +46 -0
  14. package/dist/components/axis.vue_vue_type_script_setup_true_lang.js.map +1 -0
  15. package/dist/components/bar.js +6 -0
  16. package/dist/components/bar.js.map +1 -0
  17. package/dist/components/bar.vue_vue_type_script_setup_true_lang.js +46 -0
  18. package/dist/components/bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  19. package/dist/components/boxplot.js +6 -0
  20. package/dist/components/boxplot.js.map +1 -0
  21. package/dist/components/boxplot.vue_vue_type_script_setup_true_lang.js +42 -0
  22. package/dist/components/boxplot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  23. package/dist/components/brush.js +6 -0
  24. package/dist/components/brush.js.map +1 -0
  25. package/dist/components/brush.vue_vue_type_script_setup_true_lang.js +42 -0
  26. package/dist/components/brush.vue_vue_type_script_setup_true_lang.js.map +1 -0
  27. package/dist/components/funnel.js +6 -0
  28. package/dist/components/funnel.js.map +1 -0
  29. package/dist/components/funnel.vue_vue_type_script_setup_true_lang.js +41 -0
  30. package/dist/components/funnel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  31. package/dist/components/gauge.js +6 -0
  32. package/dist/components/gauge.js.map +1 -0
  33. package/dist/components/gauge.vue_vue_type_script_setup_true_lang.js +91 -0
  34. package/dist/components/gauge.vue_vue_type_script_setup_true_lang.js.map +1 -0
  35. package/dist/components/heatmap.js +6 -0
  36. package/dist/components/heatmap.js.map +1 -0
  37. package/dist/components/heatmap.vue_vue_type_script_setup_true_lang.js +45 -0
  38. package/dist/components/heatmap.vue_vue_type_script_setup_true_lang.js.map +1 -0
  39. package/dist/components/histogram.js +6 -0
  40. package/dist/components/histogram.js.map +1 -0
  41. package/dist/components/histogram.vue_vue_type_script_setup_true_lang.js +61 -0
  42. package/dist/components/histogram.vue_vue_type_script_setup_true_lang.js.map +1 -0
  43. package/dist/components/line.js +6 -0
  44. package/dist/components/line.js.map +1 -0
  45. package/dist/components/line.vue_vue_type_script_setup_true_lang.js +52 -0
  46. package/dist/components/line.vue_vue_type_script_setup_true_lang.js.map +1 -0
  47. package/dist/components/marker.js +6 -0
  48. package/dist/components/marker.js.map +1 -0
  49. package/dist/components/marker.vue_vue_type_script_setup_true_lang.js +31 -0
  50. package/dist/components/marker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/components/pie.js +6 -0
  52. package/dist/components/pie.js.map +1 -0
  53. package/dist/components/pie.vue_vue_type_script_setup_true_lang.js +42 -0
  54. package/dist/components/pie.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/radar.js +6 -0
  56. package/dist/components/radar.js.map +1 -0
  57. package/dist/components/radar.vue_vue_type_script_setup_true_lang.js +45 -0
  58. package/dist/components/radar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/components/range.js +6 -0
  60. package/dist/components/range.js.map +1 -0
  61. package/dist/components/range.vue_vue_type_script_setup_true_lang.js +27 -0
  62. package/dist/components/range.vue_vue_type_script_setup_true_lang.js.map +1 -0
  63. package/dist/components/scatter.js +6 -0
  64. package/dist/components/scatter.js.map +1 -0
  65. package/dist/components/scatter.vue_vue_type_script_setup_true_lang.js +45 -0
  66. package/dist/components/scatter.vue_vue_type_script_setup_true_lang.js.map +1 -0
  67. package/dist/components/sunburst.js +6 -0
  68. package/dist/components/sunburst.js.map +1 -0
  69. package/dist/components/sunburst.vue_vue_type_script_setup_true_lang.js +36 -0
  70. package/dist/components/sunburst.vue_vue_type_script_setup_true_lang.js.map +1 -0
  71. package/dist/components/tooltip.js +6 -0
  72. package/dist/components/tooltip.js.map +1 -0
  73. package/dist/components/tooltip.vue_vue_type_script_setup_true_lang.js +31 -0
  74. package/dist/components/tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
  75. package/dist/components/treemap.js +6 -0
  76. package/dist/components/treemap.js.map +1 -0
  77. package/dist/components/treemap.vue_vue_type_script_setup_true_lang.js +33 -0
  78. package/dist/components/treemap.vue_vue_type_script_setup_true_lang.js.map +1 -0
  79. package/dist/components/waterfall.js +6 -0
  80. package/dist/components/waterfall.js.map +1 -0
  81. package/dist/components/waterfall.vue_vue_type_script_setup_true_lang.js +49 -0
  82. package/dist/components/waterfall.vue_vue_type_script_setup_true_lang.js.map +1 -0
  83. package/dist/components/zoom.js +6 -0
  84. package/dist/components/zoom.js.map +1 -0
  85. package/dist/components/zoom.vue_vue_type_script_setup_true_lang.js +37 -0
  86. package/dist/components/zoom.vue_vue_type_script_setup_true_lang.js.map +1 -0
  87. package/dist/context.js +30 -0
  88. package/dist/context.js.map +1 -0
  89. package/dist/core/bar.js +223 -0
  90. package/dist/core/bar.js.map +1 -0
  91. package/dist/core/box.js +150 -0
  92. package/dist/core/box.js.map +1 -0
  93. package/dist/core/colors.js +58 -0
  94. package/dist/core/colors.js.map +1 -0
  95. package/dist/core/data.js +257 -0
  96. package/dist/core/data.js.map +1 -0
  97. package/dist/core/decimate.js +211 -0
  98. package/dist/core/decimate.js.map +1 -0
  99. package/dist/core/format.js +151 -0
  100. package/dist/core/format.js.map +1 -0
  101. package/dist/core/funnel.js +68 -0
  102. package/dist/core/funnel.js.map +1 -0
  103. package/dist/core/grid.js +87 -0
  104. package/dist/core/grid.js.map +1 -0
  105. package/dist/core/heatmap.js +187 -0
  106. package/dist/core/heatmap.js.map +1 -0
  107. package/dist/core/histogram.js +81 -0
  108. package/dist/core/histogram.js.map +1 -0
  109. package/dist/core/hit.js +115 -0
  110. package/dist/core/hit.js.map +1 -0
  111. package/dist/core/labels.js +141 -0
  112. package/dist/core/labels.js.map +1 -0
  113. package/dist/core/layout.js +1002 -0
  114. package/dist/core/layout.js.map +1 -0
  115. package/dist/core/line.js +230 -0
  116. package/dist/core/line.js.map +1 -0
  117. package/dist/core/marker.js +205 -0
  118. package/dist/core/marker.js.map +1 -0
  119. package/dist/core/model.js +391 -0
  120. package/dist/core/model.js.map +1 -0
  121. package/dist/core/painter.js +79 -0
  122. package/dist/core/painter.js.map +1 -0
  123. package/dist/core/pattern.js +102 -0
  124. package/dist/core/pattern.js.map +1 -0
  125. package/dist/core/pie.js +119 -0
  126. package/dist/core/pie.js.map +1 -0
  127. package/dist/core/radar.js +83 -0
  128. package/dist/core/radar.js.map +1 -0
  129. package/dist/core/scale.js +149 -0
  130. package/dist/core/scale.js.map +1 -0
  131. package/dist/core/scatter.js +263 -0
  132. package/dist/core/scatter.js.map +1 -0
  133. package/dist/core/svg.js +209 -0
  134. package/dist/core/svg.js.map +1 -0
  135. package/dist/core/sync.js +21 -0
  136. package/dist/core/sync.js.map +1 -0
  137. package/dist/core/time.js +217 -0
  138. package/dist/core/time.js.map +1 -0
  139. package/dist/core/tree.js +348 -0
  140. package/dist/core/tree.js.map +1 -0
  141. package/dist/core/warn.js +11 -0
  142. package/dist/core/warn.js.map +1 -0
  143. package/dist/core/waterfall.js +134 -0
  144. package/dist/core/waterfall.js.map +1 -0
  145. package/dist/core/window.js +94 -0
  146. package/dist/core/window.js.map +1 -0
  147. package/dist/define.js +62 -0
  148. package/dist/define.js.map +1 -0
  149. package/dist/index.js +49 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/locale.js +170 -0
  152. package/dist/locale.js.map +1 -0
  153. package/dist/overlay.js +6 -0
  154. package/dist/overlay.js.map +1 -0
  155. package/dist/overlay.vue_vue_type_script_setup_true_lang.js +207 -0
  156. package/dist/overlay.vue_vue_type_script_setup_true_lang.js.map +1 -0
  157. package/dist/pointer.js +6 -0
  158. package/dist/pointer.js.map +1 -0
  159. package/dist/pointer.vue_vue_type_script_setup_true_lang.js +136 -0
  160. package/dist/pointer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  161. package/dist/static.js +6 -0
  162. package/dist/static.js.map +1 -0
  163. package/dist/static.vue_vue_type_script_setup_true_lang.js +34 -0
  164. package/dist/static.vue_vue_type_script_setup_true_lang.js.map +1 -0
  165. package/dist/style.css +1 -0
  166. package/dist/style.d.ts +1 -0
  167. package/dist/style.js +3 -0
  168. package/dist/table.js +6 -0
  169. package/dist/table.js.map +1 -0
  170. package/dist/table.vue_vue_type_script_setup_true_lang.js +52 -0
  171. package/dist/table.vue_vue_type_script_setup_true_lang.js.map +1 -0
  172. package/dist/types/chart.vue.d.ts +24 -0
  173. package/dist/types/components/area.vue.d.ts +16 -0
  174. package/dist/types/components/axis.vue.d.ts +8 -0
  175. package/dist/types/components/bar.vue.d.ts +14 -0
  176. package/dist/types/components/boxplot.vue.d.ts +14 -0
  177. package/dist/types/components/brush.vue.d.ts +22 -0
  178. package/dist/types/components/funnel.vue.d.ts +14 -0
  179. package/dist/types/components/gauge.vue.d.ts +17 -0
  180. package/dist/types/components/heatmap.vue.d.ts +14 -0
  181. package/dist/types/components/histogram.vue.d.ts +14 -0
  182. package/dist/types/components/line.vue.d.ts +16 -0
  183. package/dist/types/components/marker.vue.d.ts +6 -0
  184. package/dist/types/components/pie.vue.d.ts +23 -0
  185. package/dist/types/components/radar.vue.d.ts +16 -0
  186. package/dist/types/components/range.vue.d.ts +12 -0
  187. package/dist/types/components/scatter.vue.d.ts +14 -0
  188. package/dist/types/components/sunburst.vue.d.ts +17 -0
  189. package/dist/types/components/tooltip.vue.d.ts +13 -0
  190. package/dist/types/components/treemap.vue.d.ts +8 -0
  191. package/dist/types/components/waterfall.vue.d.ts +16 -0
  192. package/dist/types/components/zoom.vue.d.ts +18 -0
  193. package/dist/types/context.d.ts +87 -0
  194. package/dist/types/core/bar.d.ts +38 -0
  195. package/dist/types/core/box.d.ts +25 -0
  196. package/dist/types/core/colors.d.ts +16 -0
  197. package/dist/types/core/data.d.ts +72 -0
  198. package/dist/types/core/decimate.d.ts +39 -0
  199. package/dist/types/core/format.d.ts +33 -0
  200. package/dist/types/core/funnel.d.ts +15 -0
  201. package/dist/types/core/grid.d.ts +18 -0
  202. package/dist/types/core/heatmap.d.ts +17 -0
  203. package/dist/types/core/histogram.d.ts +23 -0
  204. package/dist/types/core/hit.d.ts +31 -0
  205. package/dist/types/core/labels.d.ts +45 -0
  206. package/dist/types/core/layout.d.ts +259 -0
  207. package/dist/types/core/line.d.ts +36 -0
  208. package/dist/types/core/marker.d.ts +67 -0
  209. package/dist/types/core/model.d.ts +86 -0
  210. package/dist/types/core/painter.d.ts +34 -0
  211. package/dist/types/core/pattern.d.ts +14 -0
  212. package/dist/types/core/pie.d.ts +66 -0
  213. package/dist/types/core/radar.d.ts +12 -0
  214. package/dist/types/core/scale.d.ts +60 -0
  215. package/dist/types/core/scatter.d.ts +16 -0
  216. package/dist/types/core/series.d.ts +228 -0
  217. package/dist/types/core/svg.d.ts +63 -0
  218. package/dist/types/core/sync.d.ts +8 -0
  219. package/dist/types/core/time.d.ts +20 -0
  220. package/dist/types/core/tree.d.ts +84 -0
  221. package/dist/types/core/warn.d.ts +4 -0
  222. package/dist/types/core/waterfall.d.ts +24 -0
  223. package/dist/types/core/window.d.ts +36 -0
  224. package/dist/types/define.d.ts +115 -0
  225. package/dist/types/index.d.ts +363 -0
  226. package/dist/types/locale.d.ts +100 -0
  227. package/dist/types/overlay.vue.d.ts +95 -0
  228. package/dist/types/pointer.vue.d.ts +53 -0
  229. package/dist/types/static.vue.d.ts +24 -0
  230. package/dist/types/table.vue.d.ts +19 -0
  231. package/dist/types/types.d.ts +555 -0
  232. package/dist/types/zoom-layer.vue.d.ts +41 -0
  233. package/dist/zoom-layer.js +6 -0
  234. package/dist/zoom-layer.js.map +1 -0
  235. package/dist/zoom-layer.vue_vue_type_script_setup_true_lang.js +210 -0
  236. package/dist/zoom-layer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  237. package/package.json +53 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern.js","names":[],"sources":["../../src/core/pattern.ts"],"sourcesContent":["import type { Painter, Rect } from './painter'\n\n/*\n * Patterns over a fill, so series and slices can be told apart without\n * their colors: in print, in grays, or for eyes that see the colors alike.\n * A pattern is drawn as lines (or dots) over the shape, clipped to it.\n */\n\nexport type ChartPattern =\n 'diagonal' | 'dots' | 'crosshatch' | 'horizontal' | 'backslash' | 'grid' | 'vertical'\n\n/** The patterns in the order series and slices take them. */\nexport const CHART_PATTERNS: readonly ChartPattern[] = [\n 'diagonal',\n 'dots',\n 'crosshatch',\n 'horizontal',\n 'backslash',\n 'grid',\n 'vertical',\n]\n\n/** The room between lines (and dots), in px. */\nconst STEP = 6\n\n/**\n * Draws `pattern` over `box` in `ink`, clipped to the current path: call\n * it right after filling a shape, while its path is still the current one.\n */\nexport function fillPattern(\n painter: Painter,\n pattern: ChartPattern,\n box: Rect,\n ink: string,\n alpha = 0.6,\n) {\n if (!(box.width > 0) || !(box.height > 0)) return\n painter.save()\n painter.clip()\n painter.globalAlpha *= alpha\n painter.strokeStyle = ink\n painter.fillStyle = ink\n painter.lineWidth = 1.25\n painter.lineCap = 'butt'\n painter.setLineDash([])\n // lines on a grid fixed to the chart, so neighboring shapes line up\n const x0 = Math.floor(box.x / STEP) * STEP\n const y0 = Math.floor(box.y / STEP) * STEP\n const x1 = box.x + box.width\n const y1 = box.y + box.height\n painter.beginPath()\n const lines = (dx: number, dy: number) => {\n // lines across the box at an angle: `dx` across for every `dy` down\n const span = x1 - x0 + (y1 - y0)\n for (let k = -span; k <= span; k += STEP) {\n if (dy === 0) {\n painter.moveTo(x0, y0 + k + STEP / 2)\n painter.lineTo(x1, y0 + k + STEP / 2)\n } else if (dx === 0) {\n painter.moveTo(x0 + k + STEP / 2, y0)\n painter.lineTo(x0 + k + STEP / 2, y1)\n } else {\n painter.moveTo(x0 + k, y0)\n painter.lineTo(x0 + k + (dx / dy) * (y1 - y0), y1)\n }\n }\n }\n switch (pattern) {\n case 'diagonal':\n lines(-1, 1)\n break\n case 'backslash':\n lines(1, 1)\n break\n case 'horizontal':\n lines(1, 0)\n break\n case 'vertical':\n lines(0, 1)\n break\n case 'crosshatch':\n lines(-1, 1)\n lines(1, 1)\n break\n case 'grid':\n lines(1, 0)\n lines(0, 1)\n break\n case 'dots': {\n const r = 1.1\n for (let y = y0 + STEP / 2; y < y1 + STEP; y += STEP)\n for (let x = x0 + STEP / 2; x < x1 + STEP; x += STEP) {\n // every other row shifted half a step, so the dots don't line up in columns\n const u = x + ((Math.round((y - y0) / STEP) % 2) * STEP) / 2\n painter.moveTo(u + r, y)\n painter.arc(u, y, r, 0, Math.PI * 2)\n }\n painter.fill()\n painter.restore()\n return\n }\n }\n painter.stroke()\n painter.restore()\n}\n\n/** The same pattern for a legend swatch, as a CSS background image and its size. */\nexport function patternCss(pattern: ChartPattern, ink: string): { image: string; size?: string } {\n return pattern === 'dots'\n ? { image: `radial-gradient(${ink} 0.75px, transparent 1px)`, size: '3px 3px' }\n : { image: linesCss(pattern, ink) }\n}\n\nfunction linesCss(pattern: Exclude<ChartPattern, 'dots'>, ink: string): string {\n const line = (angle: number) =>\n `repeating-linear-gradient(${angle}deg, ${ink} 0 1px, transparent 1px 3px)`\n switch (pattern) {\n // the stripes of a gradient run across its angle: 135deg makes them lean like /\n case 'diagonal':\n return line(135)\n case 'backslash':\n return line(45)\n case 'horizontal':\n return line(0)\n case 'vertical':\n return line(90)\n case 'crosshatch':\n return `${line(45)}, ${line(-45)}`\n case 'grid':\n return `${line(0)}, ${line(90)}`\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ import { fillPattern } from "./pattern.js";
2
+ import { read, rowOf, yColumn } from "./data.js";
3
+ // src/core/pie.ts
4
+ /**
5
+ * How far out a slice reaches, from a hole of `inner` px to `radius` px:
6
+ * a rose's slice by area, so twice the value covers twice the ink.
7
+ */
8
+ function sliceOuter(slice, inner, radius) {
9
+ if (slice.reach >= 1) return radius;
10
+ return Math.sqrt(inner * inner + (radius * radius - inner * inner) * slice.reach);
11
+ }
12
+ /**
13
+ * The slices of `rows`: one per row with a value above 0, in the order
14
+ * given, going round clockwise from the top. Slices named in `hidden`
15
+ * are kept, with no room, so they keep their place and color.
16
+ */
17
+ function pieSlices(rows, value, label, color, hidden, shape = {}) {
18
+ const values = yColumn(rows, value);
19
+ const off = new Set(hidden);
20
+ const slices = [];
21
+ let total = 0;
22
+ for (let i = 0; i < values.length; i++) {
23
+ const v = values[i];
24
+ if (!(v > 0)) continue;
25
+ const text = label === void 0 ? void 0 : read(rowOf(rows, i), label, i);
26
+ const own = color === void 0 ? void 0 : read(rowOf(rows, i), color, i);
27
+ const name = text == null ? `${i + 1}` : String(text);
28
+ const slice = {
29
+ index: i,
30
+ label: name,
31
+ color: own == null || own === "" ? void 0 : String(own),
32
+ value: v,
33
+ share: 0,
34
+ hidden: off.has(name),
35
+ start: 0,
36
+ end: 0,
37
+ reach: 1
38
+ };
39
+ if (!slice.hidden) total += v;
40
+ slices.push(slice);
41
+ }
42
+ const from = shape.start ?? 0;
43
+ const span = Math.max(0, Math.min(Math.PI * 2, (shape.end ?? from + Math.PI * 2) - from));
44
+ const shown = slices.filter((slice) => !slice.hidden);
45
+ const most = Math.max(0, ...shown.map((slice) => slice.value));
46
+ let angle = from;
47
+ for (const slice of slices) {
48
+ slice.start = angle;
49
+ if (!slice.hidden && total > 0) {
50
+ slice.share = slice.value / total;
51
+ angle += shape.rose ? span / shown.length : slice.share * span;
52
+ if (shape.rose) slice.reach = slice.value / most;
53
+ }
54
+ slice.end = angle;
55
+ }
56
+ return slices;
57
+ }
58
+ /** Angles are from 12 o'clock; the canvas counts from 3 o'clock. */
59
+ var at = (angle) => angle - Math.PI / 2;
60
+ /** How much of a series or slice shows while another is brought forward. */
61
+ var FADED = .24;
62
+ /** Room between slices, in px. */
63
+ var GAP = 2;
64
+ /**
65
+ * Draws the slices around `cx, cy`, from `inner` (0 for a pie) to
66
+ * `radius`, with a gap of the chart's surface color between them. With
67
+ * `focus`, the other slices are faded; `sweep` (0 to 1) draws only that
68
+ * much of the way round, for the pie to come in.
69
+ */
70
+ function drawPie(painter, slices, colors, { cx, cy, radius, inner, surface, focus = -1, fade = FADED, sweep = 1, from = 0, patterns }) {
71
+ const turn = (angle) => from + (angle - from) * sweep;
72
+ const shown = slices.filter((slice) => slice.end > slice.start);
73
+ slices.forEach((slice, k) => {
74
+ if (!(slice.end > slice.start)) return;
75
+ painter.save();
76
+ painter.fillStyle = colors[k];
77
+ if (focus >= 0 && slice.index !== focus) painter.globalAlpha = fade;
78
+ painter.beginPath();
79
+ const outer = sliceOuter(slice, inner, radius);
80
+ painter.arc(cx, cy, outer, at(turn(slice.start)), at(turn(slice.end)));
81
+ if (inner > 0) painter.arc(cx, cy, inner, at(turn(slice.end)), at(turn(slice.start)), true);
82
+ else painter.lineTo(cx, cy);
83
+ painter.closePath();
84
+ painter.fill();
85
+ const pattern = patterns?.[slice.index];
86
+ if (pattern) {
87
+ const box = {
88
+ x: cx - radius,
89
+ y: cy - radius,
90
+ width: radius * 2,
91
+ height: radius * 2
92
+ };
93
+ fillPattern(painter, pattern, box, surface);
94
+ }
95
+ painter.restore();
96
+ });
97
+ if (shown.length < 2) return;
98
+ painter.save();
99
+ painter.strokeStyle = surface;
100
+ painter.lineWidth = GAP;
101
+ painter.lineCap = "butt";
102
+ painter.beginPath();
103
+ const last = shown[shown.length - 1];
104
+ const whole = Math.abs(last.end - shown[0].start - Math.PI * 2) < 1e-6;
105
+ shown.forEach((slice, k) => {
106
+ const a = at(turn(slice.start));
107
+ const cos = Math.cos(a);
108
+ const sin = Math.sin(a);
109
+ const before = k > 0 ? shown[k - 1] : whole ? last : void 0;
110
+ const end = sliceOuter({ reach: Math.max(slice.reach, before?.reach ?? 0) }, inner, radius) + 1;
111
+ painter.moveTo(cx + cos * inner, cy + sin * inner);
112
+ painter.lineTo(cx + cos * end, cy + sin * end);
113
+ });
114
+ painter.stroke();
115
+ painter.restore();
116
+ }
117
+ export { FADED, drawPie, pieSlices, sliceOuter };
118
+
119
+ //# sourceMappingURL=pie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pie.js","names":[],"sources":["../../src/core/pie.ts"],"sourcesContent":["import { read, yColumn, type ChartAccessor, type ChartData, rowOf } from './data'\nimport type { Painter } from './painter'\nimport { fillPattern, type ChartPattern } from './pattern'\n\n/** A slice of a pie, with its angles in radians clockwise from 12 o'clock. */\nexport interface PieSlice {\n /** The row's index. */\n index: number\n label: string\n value: number\n /** Its own color, if the pie reads one. */\n color?: string\n /** Its part of the whole, 0 to 1; 0 when hidden. */\n share: number\n /** Turned off in the legend: it keeps its color, but takes no room. */\n hidden: boolean\n start: number\n end: number\n /**\n * How much of its ring it fills, 0 to 1: 1, but for a rose, whose\n * slices share the turn evenly and fill out by their values.\n */\n reach: number\n}\n\n/**\n * How far out a slice reaches, from a hole of `inner` px to `radius` px:\n * a rose's slice by area, so twice the value covers twice the ink.\n */\nexport function sliceOuter(slice: Pick<PieSlice, 'reach'>, inner: number, radius: number) {\n if (slice.reach >= 1) return radius\n return Math.sqrt(inner * inner + (radius * radius - inner * inner) * slice.reach)\n}\n\n/** The part of the turn a pie takes, and whether it is a rose. */\nexport interface PieShape {\n /** Where the slices start and end, in radians clockwise from 12 o'clock. */\n start?: number\n end?: number\n /** Each slice the same angle, its area (not its angle) by its value. */\n rose?: boolean\n}\n\n/**\n * The slices of `rows`: one per row with a value above 0, in the order\n * given, going round clockwise from the top. Slices named in `hidden`\n * are kept, with no room, so they keep their place and color.\n */\nexport function pieSlices(\n rows: ChartData,\n value: ChartAccessor,\n label: ChartAccessor | undefined,\n color?: ChartAccessor,\n hidden?: readonly string[],\n shape: PieShape = {},\n): PieSlice[] {\n const values = yColumn(rows, value)\n const off = new Set(hidden)\n const slices: PieSlice[] = []\n let total = 0\n for (let i = 0; i < values.length; i++) {\n const v = values[i]!\n if (!(v > 0)) continue\n const text = label === undefined ? undefined : read(rowOf(rows, i), label, i)\n const own = color === undefined ? undefined : read(rowOf(rows, i), color, i)\n const name = text == null ? `${i + 1}` : String(text)\n const slice = {\n index: i,\n label: name,\n color: own == null || own === '' ? undefined : String(own),\n value: v,\n share: 0,\n hidden: off.has(name),\n start: 0,\n end: 0,\n reach: 1,\n }\n if (!slice.hidden) total += v\n slices.push(slice)\n }\n const from = shape.start ?? 0\n const span = Math.max(0, Math.min(Math.PI * 2, (shape.end ?? from + Math.PI * 2) - from))\n const shown = slices.filter((slice) => !slice.hidden)\n // a rose: the largest reaches the rim, the others by area, so the eye compares amounts\n const most = Math.max(0, ...shown.map((slice) => slice.value))\n let angle = from\n for (const slice of slices) {\n slice.start = angle\n if (!slice.hidden && total > 0) {\n slice.share = slice.value / total\n angle += shape.rose ? span / shown.length : slice.share * span\n if (shape.rose) slice.reach = slice.value / most\n }\n slice.end = angle\n }\n return slices\n}\n\n/** Angles are from 12 o'clock; the canvas counts from 3 o'clock. */\nconst at = (angle: number) => angle - Math.PI / 2\n\n/** How much of a series or slice shows while another is brought forward. */\nexport const FADED = 0.24\n\n/** Room between slices, in px. */\nconst GAP = 2\n\n/**\n * Draws the slices around `cx, cy`, from `inner` (0 for a pie) to\n * `radius`, with a gap of the chart's surface color between them. With\n * `focus`, the other slices are faded; `sweep` (0 to 1) draws only that\n * much of the way round, for the pie to come in.\n */\nexport function drawPie(\n painter: Painter,\n slices: PieSlice[],\n colors: string[],\n {\n cx,\n cy,\n radius,\n inner,\n surface,\n focus = -1,\n fade = FADED,\n sweep = 1,\n from = 0,\n patterns,\n }: {\n cx: number\n cy: number\n radius: number\n inner: number\n surface: string\n /** The `index` of the slice to bring forward. */\n focus?: number\n /** How much the other slices show. */\n fade?: number\n sweep?: number\n /** Where the slices start: coming in, they sweep round from there. */\n from?: number\n /** The pattern over each slice, by its `index`. */\n patterns?: Array<ChartPattern | null>\n },\n) {\n const turn = (angle: number) => from + (angle - from) * sweep\n const shown = slices.filter((slice) => slice.end > slice.start)\n slices.forEach((slice, k) => {\n if (!(slice.end > slice.start)) return\n painter.save()\n painter.fillStyle = colors[k]!\n if (focus >= 0 && slice.index !== focus) painter.globalAlpha = fade\n painter.beginPath()\n // a rose's slice reaches out by its value, from the hole's edge\n const outer = sliceOuter(slice, inner, radius)\n painter.arc(cx, cy, outer, at(turn(slice.start)), at(turn(slice.end)))\n if (inner > 0) painter.arc(cx, cy, inner, at(turn(slice.end)), at(turn(slice.start)), true)\n else painter.lineTo(cx, cy)\n painter.closePath()\n painter.fill()\n const pattern = patterns?.[slice.index]\n if (pattern) {\n const box = { x: cx - radius, y: cy - radius, width: radius * 2, height: radius * 2 }\n fillPattern(painter, pattern, box, surface)\n }\n painter.restore()\n })\n if (shown.length < 2) return\n // the gaps: lines of surface color along each edge, the same width all the way out\n painter.save()\n painter.strokeStyle = surface\n painter.lineWidth = GAP\n painter.lineCap = 'butt'\n painter.beginPath()\n // round the whole circle, the first slice meets the last\n const last = shown[shown.length - 1]!\n const whole = Math.abs(last.end - shown[0]!.start - Math.PI * 2) < 1e-6\n shown.forEach((slice, k) => {\n const a = at(turn(slice.start))\n const cos = Math.cos(a)\n const sin = Math.sin(a)\n // out to the longer of the two slices the edge is between (a rose's differ)\n const before = k > 0 ? shown[k - 1] : whole ? last : undefined\n const end = sliceOuter({ reach: Math.max(slice.reach, before?.reach ?? 0) }, inner, radius) + 1\n painter.moveTo(cx + cos * inner, cy + sin * inner)\n painter.lineTo(cx + cos * end, cy + sin * end)\n })\n painter.stroke()\n painter.restore()\n}\n"],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import { tracePoints } from "./painter.js";
2
+ // src/core/radar.ts
3
+ /** The most spokes a series gets dots on by default: more crowd the rim. */
4
+ var DOT_SPOKES = 12;
5
+ /** The angle of spoke `index` of `count`, clockwise from 12 o'clock. */
6
+ function spokeAngle(index, count) {
7
+ return index / Math.max(1, count) * Math.PI * 2;
8
+ }
9
+ /** The spoke nearest the angle `angle` (clockwise from 12 o'clock), of `count`. */
10
+ function nearestSpoke(angle, count) {
11
+ if (count < 1) return -1;
12
+ const step = Math.PI * 2 / count;
13
+ return Math.round(angle / step) % count;
14
+ }
15
+ /** A radar's corners in px, in spoke order, for the rows with a value. */
16
+ function corners(series, view) {
17
+ const order = [];
18
+ for (let i = 0; i < series.top.length; i++) {
19
+ const x = series.x.values[i];
20
+ if (x === x && series.top[i] === series.top[i]) order.push(i);
21
+ }
22
+ order.sort((a, b) => series.x.values[a] - series.x.values[b]);
23
+ const xs = new Float64Array(order.length);
24
+ const ys = new Float64Array(order.length);
25
+ order.forEach((i, k) => {
26
+ const [left, top] = view.point(series.x.values[i], series.top[i]);
27
+ xs[k] = left;
28
+ ys[k] = top;
29
+ });
30
+ return {
31
+ xs,
32
+ ys,
33
+ count: order.length
34
+ };
35
+ }
36
+ var radarKind = {
37
+ type: "radar",
38
+ polar: true,
39
+ zero: true,
40
+ draw(painter, series, view) {
41
+ const { xs, ys, count } = corners(series, view);
42
+ if (!count) return;
43
+ const style = series.props;
44
+ const lineWidth = style.lineWidth ?? 2;
45
+ painter.save();
46
+ painter.beginPath();
47
+ tracePoints(painter, xs, ys, count, {});
48
+ painter.closePath();
49
+ painter.fillStyle = series.color;
50
+ painter.globalAlpha *= .1;
51
+ painter.fill();
52
+ painter.restore();
53
+ if (lineWidth > 0) {
54
+ painter.save();
55
+ painter.beginPath();
56
+ tracePoints(painter, xs, ys, count, {});
57
+ painter.closePath();
58
+ painter.strokeStyle = series.color;
59
+ painter.lineWidth = lineWidth;
60
+ painter.lineJoin = "round";
61
+ painter.stroke();
62
+ painter.restore();
63
+ }
64
+ const spokes = view.polar?.count ?? count;
65
+ if (!(style.dots ?? (spokes <= DOT_SPOKES || count === 1))) return;
66
+ const r = Math.max(2.5, lineWidth + .5);
67
+ painter.save();
68
+ painter.fillStyle = series.color;
69
+ painter.strokeStyle = view.colors.surface;
70
+ painter.lineWidth = 1.5;
71
+ painter.beginPath();
72
+ for (let k = 0; k < count; k++) {
73
+ painter.moveTo(xs[k] + r, ys[k]);
74
+ painter.arc(xs[k], ys[k], r, 0, Math.PI * 2);
75
+ }
76
+ painter.stroke();
77
+ painter.fill();
78
+ painter.restore();
79
+ }
80
+ };
81
+ export { nearestSpoke, radarKind, spokeAngle };
82
+
83
+ //# sourceMappingURL=radar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radar.js","names":[],"sources":["../../src/core/radar.ts"],"sourcesContent":["import { tracePoints, type Painter } from './painter'\nimport type { ChartSeries, ChartSeriesKind, ChartView } from './series'\n\n/*\n * A radar: a spoke for each category, evenly round from 12 o'clock and\n * clockwise, and for each series a closed shape through its values along\n * them, from 0 at the center out to the largest value at the rim. The\n * rings of the grid are polygons, so equal values lie on straight lines.\n */\n\nexport interface RadarStyle {\n /** Dots on the corners: `true`, `false`, or (the default) when there are few. */\n dots?: boolean\n /** The width of the outline, in px. */\n lineWidth?: number\n}\n\n/** The most spokes a series gets dots on by default: more crowd the rim. */\nconst DOT_SPOKES = 12\n\n/** The angle of spoke `index` of `count`, clockwise from 12 o'clock. */\nexport function spokeAngle(index: number, count: number): number {\n return (index / Math.max(1, count)) * Math.PI * 2\n}\n\n/** The spoke nearest the angle `angle` (clockwise from 12 o'clock), of `count`. */\nexport function nearestSpoke(angle: number, count: number): number {\n if (count < 1) return -1\n const step = (Math.PI * 2) / count\n return Math.round(angle / step) % count\n}\n\n/** A radar's corners in px, in spoke order, for the rows with a value. */\nfunction corners(series: ChartSeries<RadarStyle>, view: ChartView) {\n const order: number[] = []\n for (let i = 0; i < series.top.length; i++) {\n const x = series.x.values[i]!\n if (x === x && series.top[i] === series.top[i]) order.push(i)\n }\n order.sort((a, b) => series.x.values[a]! - series.x.values[b]!)\n const xs = new Float64Array(order.length)\n const ys = new Float64Array(order.length)\n order.forEach((i, k) => {\n const [left, top] = view.point(series.x.values[i]!, series.top[i]!)\n xs[k] = left\n ys[k] = top\n })\n return { xs, ys, count: order.length }\n}\n\nexport const radarKind: ChartSeriesKind<RadarStyle> = {\n type: 'radar',\n polar: true,\n zero: true,\n draw(painter: Painter, series, view) {\n const { xs, ys, count } = corners(series, view)\n if (!count) return\n const style = series.props\n const lineWidth = style.lineWidth ?? 2\n painter.save()\n painter.beginPath()\n tracePoints(painter, xs, ys, count, {})\n painter.closePath()\n painter.fillStyle = series.color\n painter.globalAlpha *= 0.1\n painter.fill()\n painter.restore()\n if (lineWidth > 0) {\n painter.save()\n painter.beginPath()\n tracePoints(painter, xs, ys, count, {})\n painter.closePath()\n painter.strokeStyle = series.color\n painter.lineWidth = lineWidth\n painter.lineJoin = 'round'\n painter.stroke()\n painter.restore()\n }\n const spokes = view.polar?.count ?? count\n if (!(style.dots ?? (spokes <= DOT_SPOKES || count === 1))) return\n const r = Math.max(2.5, lineWidth + 0.5)\n painter.save()\n painter.fillStyle = series.color\n painter.strokeStyle = view.colors.surface\n painter.lineWidth = 1.5\n painter.beginPath()\n for (let k = 0; k < count; k++) {\n painter.moveTo(xs[k]! + r, ys[k]!)\n painter.arc(xs[k]!, ys[k]!, r, 0, Math.PI * 2)\n }\n painter.stroke()\n painter.fill()\n painter.restore()\n },\n}\n"],"mappings":";;;AAkBA,IAAM,aAAa;;AAGnB,SAAgB,WAAW,OAAe,OAAuB;CAC/D,OAAQ,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAK,KAAK,KAAK;AAClD;;AAGA,SAAgB,aAAa,OAAe,OAAuB;CACjE,IAAI,QAAQ,GAAG,OAAO;CACtB,MAAM,OAAQ,KAAK,KAAK,IAAK;CAC7B,OAAO,KAAK,MAAM,QAAQ,IAAI,IAAI;AACpC;;AAGA,SAAS,QAAQ,QAAiC,MAAiB;CACjE,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,IAAI,QAAQ,KAAK;EAC1C,MAAM,IAAI,OAAO,EAAE,OAAO;EAC1B,IAAI,MAAM,KAAK,OAAO,IAAI,OAAO,OAAO,IAAI,IAAI,MAAM,KAAK,CAAC;CAC9D;CACA,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,OAAO,KAAM,OAAO,EAAE,OAAO,EAAG;CAC9D,MAAM,KAAK,IAAI,aAAa,MAAM,MAAM;CACxC,MAAM,KAAK,IAAI,aAAa,MAAM,MAAM;CACxC,MAAM,SAAS,GAAG,MAAM;EACtB,MAAM,CAAC,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE,OAAO,IAAK,OAAO,IAAI,EAAG;EAClE,GAAG,KAAK;EACR,GAAG,KAAK;CACV,CAAC;CACD,OAAO;EAAE;EAAI;EAAI,OAAO,MAAM;CAAO;AACvC;AAEA,IAAa,YAAyC;CACpD,MAAM;CACN,OAAO;CACP,MAAM;CACN,KAAK,SAAkB,QAAQ,MAAM;EACnC,MAAM,EAAE,IAAI,IAAI,UAAU,QAAQ,QAAQ,IAAI;EAC9C,IAAI,CAAC,OAAO;EACZ,MAAM,QAAQ,OAAO;EACrB,MAAM,YAAY,MAAM,aAAa;EACrC,QAAQ,KAAK;EACb,QAAQ,UAAU;EAClB,YAAY,SAAS,IAAI,IAAI,OAAO,CAAC,CAAC;EACtC,QAAQ,UAAU;EAClB,QAAQ,YAAY,OAAO;EAC3B,QAAQ,eAAe;EACvB,QAAQ,KAAK;EACb,QAAQ,QAAQ;EAChB,IAAI,YAAY,GAAG;GACjB,QAAQ,KAAK;GACb,QAAQ,UAAU;GAClB,YAAY,SAAS,IAAI,IAAI,OAAO,CAAC,CAAC;GACtC,QAAQ,UAAU;GAClB,QAAQ,cAAc,OAAO;GAC7B,QAAQ,YAAY;GACpB,QAAQ,WAAW;GACnB,QAAQ,OAAO;GACf,QAAQ,QAAQ;EAClB;EACA,MAAM,SAAS,KAAK,OAAO,SAAS;EACpC,IAAI,EAAE,MAAM,SAAS,UAAU,cAAc,UAAU,KAAK;EAC5D,MAAM,IAAI,KAAK,IAAI,KAAK,YAAY,EAAG;EACvC,QAAQ,KAAK;EACb,QAAQ,YAAY,OAAO;EAC3B,QAAQ,cAAc,KAAK,OAAO;EAClC,QAAQ,YAAY;EACpB,QAAQ,UAAU;EAClB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC9B,QAAQ,OAAO,GAAG,KAAM,GAAG,GAAG,EAAG;GACjC,QAAQ,IAAI,GAAG,IAAK,GAAG,IAAK,GAAG,GAAG,KAAK,KAAK,CAAC;EAC/C;EACA,QAAQ,OAAO;EACf,QAAQ,KAAK;EACb,QAAQ,QAAQ;CAClB;AACF"}
@@ -0,0 +1,149 @@
1
+ // src/core/scale.ts
2
+ /**
3
+ * The step of 1, 2 or 5 times a power of ten that gives closest to
4
+ * `count` steps across `span` (rounding on a log scale, so it may give a
5
+ * few more or fewer).
6
+ */
7
+ function niceStep(span, count) {
8
+ const raw = span / Math.max(1, count);
9
+ if (!(raw > 0) || !Number.isFinite(raw)) return 1;
10
+ const power = 10 ** Math.floor(Math.log10(raw));
11
+ const fraction = raw / power;
12
+ return (fraction >= Math.SQRT2 * 5 ? 10 : fraction >= Math.sqrt(10) ? 5 : fraction >= Math.SQRT2 ? 2 : 1) * power;
13
+ }
14
+ /** The next nice step up: 1 → 2 → 5 → 10. */
15
+ function nextNiceStep(step) {
16
+ const power = 10 ** Math.floor(Math.log10(step) + 1e-9);
17
+ const fraction = Math.round(step / power);
18
+ return (fraction < 2 ? 2 : fraction < 5 ? 5 : 10) * power;
19
+ }
20
+ /** How many decimals tell the ticks of `step` apart. */
21
+ function stepDecimals(step) {
22
+ return Math.max(0, Math.min(20, -Math.floor(Math.log10(step) + 1e-9)));
23
+ }
24
+ var round = (value, decimals) => Number(value.toFixed(decimals));
25
+ /**
26
+ * A domain wide enough to show `[min, max]`: an empty span is widened, and
27
+ * with `nice` the ends are rounded out to the tick step for about `count` ticks.
28
+ */
29
+ function linearDomain(min, max, { count = 5, nice = true } = {}) {
30
+ if (!(min <= max)) return [0, 1];
31
+ if (min === max) {
32
+ const pad = min === 0 ? 1 : Math.abs(min) * .1;
33
+ [min, max] = [min - pad, max + pad];
34
+ if (min < 0 && max - pad >= 0) min = 0;
35
+ }
36
+ if (!nice) return [min, max];
37
+ let step = niceStep(max - min, count);
38
+ let lo = Math.floor(min / step) * step;
39
+ let hi = Math.ceil(max / step) * step;
40
+ for (let guard = 0; guard < 4 && (hi - lo) / step > count * 2 + 1e-9; guard++) {
41
+ step = nextNiceStep(step);
42
+ lo = Math.floor(min / step) * step;
43
+ hi = Math.ceil(max / step) * step;
44
+ }
45
+ const decimals = stepDecimals(step);
46
+ return [round(lo, decimals), round(hi, decimals)];
47
+ }
48
+ /** Ticks at the multiples of a nice step inside `[lo, hi]`, about `count` of them. */
49
+ function linearTicks(lo, hi, count) {
50
+ if (!(hi > lo)) return Number.isFinite(lo) ? [lo] : [];
51
+ const step = niceStep(hi - lo, count);
52
+ const decimals = stepDecimals(step);
53
+ const first = Math.ceil(lo / step - 1e-9);
54
+ const last = Math.floor(hi / step + 1e-9);
55
+ const ticks = [];
56
+ for (let i = first; i <= last; i++) ticks.push(round(i * step, decimals));
57
+ return ticks;
58
+ }
59
+ function linearScale(domain, range, kind = "linear") {
60
+ const [d0, d1] = domain;
61
+ const [r0, r1] = range;
62
+ const k = d1 === d0 ? 0 : (r1 - r0) / (d1 - d0);
63
+ const b = d1 === d0 ? (r0 + r1) / 2 : r0 - d0 * k;
64
+ return {
65
+ kind,
66
+ domain,
67
+ range,
68
+ step: 0,
69
+ categories: [],
70
+ k,
71
+ b,
72
+ map: (value) => value * k + b,
73
+ invert: (pixel) => k === 0 ? d0 : (pixel - b) / k
74
+ };
75
+ }
76
+ /** Rounds out to whole powers of ten; values at or below 0 can't be shown and are left out. */
77
+ function logDomain(min, max) {
78
+ if (!(max > 0)) return [1, 10];
79
+ if (!(min > 0)) min = max / 10;
80
+ const lo = 10 ** Math.floor(Math.log10(min));
81
+ let hi = 10 ** Math.ceil(Math.log10(max));
82
+ if (hi === lo) hi = lo * 10;
83
+ return [lo, hi];
84
+ }
85
+ function logTicks(lo, hi, count) {
86
+ const from = Math.floor(Math.log10(lo) + 1e-9);
87
+ const to = Math.ceil(Math.log10(hi) - 1e-9);
88
+ const decades = to - from;
89
+ const steps = decades * 3 <= count ? [
90
+ 1,
91
+ 2,
92
+ 5
93
+ ] : [1];
94
+ const every = Math.max(1, Math.ceil(decades / Math.max(1, count)));
95
+ const ticks = [];
96
+ for (let e = from; e <= to; e += steps.length > 1 ? 1 : every) for (const s of steps) {
97
+ const v = s * 10 ** e;
98
+ if (v >= lo * (1 - 1e-9) && v <= hi * (1 + 1e-9)) ticks.push(Number(v.toPrecision(12)));
99
+ }
100
+ return ticks;
101
+ }
102
+ function logScale(domain, range) {
103
+ const [l0, l1] = [Math.log10(domain[0]), Math.log10(domain[1])];
104
+ const [r0, r1] = range;
105
+ const k = l1 === l0 ? 0 : (r1 - r0) / (l1 - l0);
106
+ return {
107
+ kind: "log",
108
+ domain,
109
+ range,
110
+ step: 0,
111
+ categories: [],
112
+ k: NaN,
113
+ b: NaN,
114
+ map: (value) => value > 0 ? r0 + (Math.log10(value) - l0) * k : r0 - (r1 - r0) * 10,
115
+ invert: (pixel) => 10 ** (k === 0 ? l0 : l0 + (pixel - r0) / k)
116
+ };
117
+ }
118
+ /**
119
+ * Categories side by side, each in the middle of its own step. `map(i)` is
120
+ * the middle of category `i`; `domain` is `[-0.5, n - 0.5]` so that a
121
+ * category's step runs from `map(i - 0.5)` to `map(i + 0.5)`.
122
+ */
123
+ function categoryScale(categories, range) {
124
+ const n = Math.max(1, categories.length);
125
+ return {
126
+ ...linearScale([-.5, n - .5], range),
127
+ kind: "category",
128
+ step: Math.abs(range[1] - range[0]) / n,
129
+ categories
130
+ };
131
+ }
132
+ /** Every `every`-th category index, starting from the first. */
133
+ function categoryTicks(count, every = 1) {
134
+ const ticks = [];
135
+ for (let i = 0; i < count; i += every) ticks.push(i);
136
+ return ticks;
137
+ }
138
+ /**
139
+ * The pixel that areas and bars grow from: 0, or the nearer end when 0 is
140
+ * off the axis (always the start on a log axis).
141
+ */
142
+ function baseline(scale) {
143
+ if (scale.kind === "log") return scale.range[0];
144
+ const [a, b] = scale.domain;
145
+ return scale.map(Math.min(Math.max(0, Math.min(a, b)), Math.max(a, b)));
146
+ }
147
+ export { baseline, categoryScale, categoryTicks, linearDomain, linearScale, linearTicks, logDomain, logScale, logTicks, nextNiceStep, niceStep, stepDecimals };
148
+
149
+ //# sourceMappingURL=scale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scale.js","names":[],"sources":["../../src/core/scale.ts"],"sourcesContent":["/**\n * Scales turn data values into pixels and back. They are plain objects\n * with the mapping folded into two numbers, so `map` costs a multiply and\n * an add: it runs once per drawn point.\n */\n\nexport type ScaleKind = 'linear' | 'log' | 'time' | 'category'\n\nexport interface Scale {\n kind: ScaleKind\n /** The values at the two ends, after rounding to nice numbers. */\n domain: [number, number]\n /** The pixels the two ends of `domain` land on. */\n range: [number, number]\n map(value: number): number\n invert(pixel: number): number\n /** For `category`: the room each category gets, in px. 0 otherwise. */\n step: number\n /** For `category`: the categories. */\n categories: string[]\n /** For all but `log`: `map(v)` is `v * k + b`, for loops that can't afford a call per point. */\n k: number\n b: number\n}\n\n/**\n * The step of 1, 2 or 5 times a power of ten that gives closest to\n * `count` steps across `span` (rounding on a log scale, so it may give a\n * few more or fewer).\n */\nexport function niceStep(span: number, count: number): number {\n const raw = span / Math.max(1, count)\n if (!(raw > 0) || !Number.isFinite(raw)) return 1\n const power = 10 ** Math.floor(Math.log10(raw))\n const fraction = raw / power\n const nice =\n fraction >= Math.SQRT2 * 5 ? 10 : fraction >= Math.sqrt(10) ? 5 : fraction >= Math.SQRT2 ? 2 : 1\n return nice * power\n}\n\n/** The next nice step up: 1 → 2 → 5 → 10. */\nexport function nextNiceStep(step: number): number {\n const power = 10 ** Math.floor(Math.log10(step) + 1e-9)\n const fraction = Math.round(step / power)\n return (fraction < 2 ? 2 : fraction < 5 ? 5 : 10) * power\n}\n\n/** How many decimals tell the ticks of `step` apart. */\nexport function stepDecimals(step: number): number {\n return Math.max(0, Math.min(20, -Math.floor(Math.log10(step) + 1e-9)))\n}\n\nconst round = (value: number, decimals: number) => Number(value.toFixed(decimals))\n\n/**\n * A domain wide enough to show `[min, max]`: an empty span is widened, and\n * with `nice` the ends are rounded out to the tick step for about `count` ticks.\n */\nexport function linearDomain(\n min: number,\n max: number,\n { count = 5, nice = true }: { count?: number; nice?: boolean } = {},\n): [number, number] {\n if (!(min <= max)) return [0, 1]\n if (min === max) {\n const pad = min === 0 ? 1 : Math.abs(min) * 0.1\n ;[min, max] = [min - pad, max + pad]\n if (min < 0 && max - pad >= 0) min = 0\n }\n if (!nice) return [min, max]\n // rounded out to the step for the data itself, so the ends stay close to\n // it; a coarser step only when that would make too many steps\n let step = niceStep(max - min, count)\n let lo = Math.floor(min / step) * step\n let hi = Math.ceil(max / step) * step\n for (let guard = 0; guard < 4 && (hi - lo) / step > count * 2 + 1e-9; guard++) {\n step = nextNiceStep(step)\n lo = Math.floor(min / step) * step\n hi = Math.ceil(max / step) * step\n }\n const decimals = stepDecimals(step)\n return [round(lo, decimals), round(hi, decimals)]\n}\n\n/** Ticks at the multiples of a nice step inside `[lo, hi]`, about `count` of them. */\nexport function linearTicks(lo: number, hi: number, count: number): number[] {\n if (!(hi > lo)) return Number.isFinite(lo) ? [lo] : []\n const step = niceStep(hi - lo, count)\n const decimals = stepDecimals(step)\n const first = Math.ceil(lo / step - 1e-9)\n const last = Math.floor(hi / step + 1e-9)\n const ticks: number[] = []\n for (let i = first; i <= last; i++) ticks.push(round(i * step, decimals))\n return ticks\n}\n\nexport function linearScale(\n domain: [number, number],\n range: [number, number],\n kind: 'linear' | 'time' = 'linear',\n): Scale {\n const [d0, d1] = domain\n const [r0, r1] = range\n const k = d1 === d0 ? 0 : (r1 - r0) / (d1 - d0)\n const b = d1 === d0 ? (r0 + r1) / 2 : r0 - d0 * k\n return {\n kind,\n domain,\n range,\n step: 0,\n categories: [],\n k,\n b,\n map: (value) => value * k + b,\n invert: (pixel) => (k === 0 ? d0 : (pixel - b) / k),\n }\n}\n\n/* log */\n\n/** Rounds out to whole powers of ten; values at or below 0 can't be shown and are left out. */\nexport function logDomain(min: number, max: number): [number, number] {\n if (!(max > 0)) return [1, 10]\n if (!(min > 0)) min = max / 10\n const lo = 10 ** Math.floor(Math.log10(min))\n let hi = 10 ** Math.ceil(Math.log10(max))\n if (hi === lo) hi = lo * 10\n return [lo, hi]\n}\n\nexport function logTicks(lo: number, hi: number, count: number): number[] {\n const from = Math.floor(Math.log10(lo) + 1e-9)\n const to = Math.ceil(Math.log10(hi) - 1e-9)\n const decades = to - from\n // few decades: 1, 2 and 5 of each; many: every few powers of ten\n const steps = decades * 3 <= count ? [1, 2, 5] : [1]\n const every = Math.max(1, Math.ceil(decades / Math.max(1, count)))\n const ticks: number[] = []\n for (let e = from; e <= to; e += steps.length > 1 ? 1 : every) {\n for (const s of steps) {\n const v = s * 10 ** e\n if (v >= lo * (1 - 1e-9) && v <= hi * (1 + 1e-9)) ticks.push(Number(v.toPrecision(12)))\n }\n }\n return ticks\n}\n\nexport function logScale(domain: [number, number], range: [number, number]): Scale {\n const [l0, l1] = [Math.log10(domain[0]), Math.log10(domain[1])]\n const [r0, r1] = range\n const k = l1 === l0 ? 0 : (r1 - r0) / (l1 - l0)\n return {\n kind: 'log',\n domain,\n range,\n step: 0,\n categories: [],\n k: Number.NaN,\n b: Number.NaN,\n // values at or below 0 go off the bottom\n map: (value) => (value > 0 ? r0 + (Math.log10(value) - l0) * k : r0 - (r1 - r0) * 10),\n invert: (pixel) => 10 ** (k === 0 ? l0 : l0 + (pixel - r0) / k),\n }\n}\n\n/* category */\n\n/**\n * Categories side by side, each in the middle of its own step. `map(i)` is\n * the middle of category `i`; `domain` is `[-0.5, n - 0.5]` so that a\n * category's step runs from `map(i - 0.5)` to `map(i + 0.5)`.\n */\nexport function categoryScale(categories: string[], range: [number, number]): Scale {\n const n = Math.max(1, categories.length)\n const scale = linearScale([-0.5, n - 0.5], range)\n return { ...scale, kind: 'category', step: Math.abs(range[1] - range[0]) / n, categories }\n}\n\n/** Every `every`-th category index, starting from the first. */\nexport function categoryTicks(count: number, every = 1): number[] {\n const ticks: number[] = []\n for (let i = 0; i < count; i += every) ticks.push(i)\n return ticks\n}\n\n/**\n * The pixel that areas and bars grow from: 0, or the nearer end when 0 is\n * off the axis (always the start on a log axis).\n */\nexport function baseline(scale: Scale): number {\n if (scale.kind === 'log') return scale.range[0]\n const [a, b] = scale.domain\n return scale.map(Math.min(Math.max(0, Math.min(a, b)), Math.max(a, b)))\n}\n"],"mappings":";;;;;;AA8BA,SAAgB,SAAS,MAAc,OAAuB;CAC5D,MAAM,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK;CACpC,IAAI,EAAE,MAAM,MAAM,CAAC,OAAO,SAAS,GAAG,GAAG,OAAO;CAChD,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAC;CAC9C,MAAM,WAAW,MAAM;CAGvB,QADE,YAAY,KAAK,QAAQ,IAAI,KAAK,YAAY,KAAK,KAAK,EAAE,IAAI,IAAI,YAAY,KAAK,QAAQ,IAAI,KACnF;AAChB;;AAGA,SAAgB,aAAa,MAAsB;CACjD,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI;CACtD,MAAM,WAAW,KAAK,MAAM,OAAO,KAAK;CACxC,QAAQ,WAAW,IAAI,IAAI,WAAW,IAAI,IAAI,MAAM;AACtD;;AAGA,SAAgB,aAAa,MAAsB;CACjD,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,MAAM,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,CAAC;AACvE;AAEA,IAAM,SAAS,OAAe,aAAqB,OAAO,MAAM,QAAQ,QAAQ,CAAC;;;;;AAMjF,SAAgB,aACd,KACA,KACA,EAAE,QAAQ,GAAG,OAAO,SAA6C,CAAC,GAChD;CAClB,IAAI,EAAE,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC;CAC/B,IAAI,QAAQ,KAAK;EACf,MAAM,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI;EAC3C,CAAC,KAAK,OAAO,CAAC,MAAM,KAAK,MAAM,GAAG;EACnC,IAAI,MAAM,KAAK,MAAM,OAAO,GAAG,MAAM;CACvC;CACA,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,GAAG;CAG3B,IAAI,OAAO,SAAS,MAAM,KAAK,KAAK;CACpC,IAAI,KAAK,KAAK,MAAM,MAAM,IAAI,IAAI;CAClC,IAAI,KAAK,KAAK,KAAK,MAAM,IAAI,IAAI;CACjC,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,KAAK,MAAM,OAAO,QAAQ,IAAI,MAAM,SAAS;EAC7E,OAAO,aAAa,IAAI;EACxB,KAAK,KAAK,MAAM,MAAM,IAAI,IAAI;EAC9B,KAAK,KAAK,KAAK,MAAM,IAAI,IAAI;CAC/B;CACA,MAAM,WAAW,aAAa,IAAI;CAClC,OAAO,CAAC,MAAM,IAAI,QAAQ,GAAG,MAAM,IAAI,QAAQ,CAAC;AAClD;;AAGA,SAAgB,YAAY,IAAY,IAAY,OAAyB;CAC3E,IAAI,EAAE,KAAK,KAAK,OAAO,OAAO,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;CACrD,MAAM,OAAO,SAAS,KAAK,IAAI,KAAK;CACpC,MAAM,WAAW,aAAa,IAAI;CAClC,MAAM,QAAQ,KAAK,KAAK,KAAK,OAAO,IAAI;CACxC,MAAM,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI;CACxC,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,IAAI,MAAM,QAAQ,CAAC;CACxE,OAAO;AACT;AAEA,SAAgB,YACd,QACA,OACA,OAA0B,UACnB;CACP,MAAM,CAAC,IAAI,MAAM;CACjB,MAAM,CAAC,IAAI,MAAM;CACjB,MAAM,IAAI,OAAO,KAAK,KAAK,KAAK,OAAO,KAAK;CAC5C,MAAM,IAAI,OAAO,MAAM,KAAK,MAAM,IAAI,KAAK,KAAK;CAChD,OAAO;EACL;EACA;EACA;EACA,MAAM;EACN,YAAY,CAAC;EACb;EACA;EACA,MAAM,UAAU,QAAQ,IAAI;EAC5B,SAAS,UAAW,MAAM,IAAI,MAAM,QAAQ,KAAK;CACnD;AACF;;AAKA,SAAgB,UAAU,KAAa,KAA+B;CACpE,IAAI,EAAE,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE;CAC7B,IAAI,EAAE,MAAM,IAAI,MAAM,MAAM;CAC5B,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG,CAAC;CAC3C,IAAI,KAAK,MAAM,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC;CACxC,IAAI,OAAO,IAAI,KAAK,KAAK;CACzB,OAAO,CAAC,IAAI,EAAE;AAChB;AAEA,SAAgB,SAAS,IAAY,IAAY,OAAyB;CACxE,MAAM,OAAO,KAAK,MAAM,KAAK,MAAM,EAAE,IAAI,IAAI;CAC7C,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,EAAE,IAAI,IAAI;CAC1C,MAAM,UAAU,KAAK;CAErB,MAAM,QAAQ,UAAU,KAAK,QAAQ;EAAC;EAAG;EAAG;CAAC,IAAI,CAAC,CAAC;CACnD,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,KAAK,IAAI,GAAG,KAAK,CAAC,CAAC;CACjE,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,KAAK,MAAM,SAAS,IAAI,IAAI,OACtD,KAAK,MAAM,KAAK,OAAO;EACrB,MAAM,IAAI,IAAI,MAAM;EACpB,IAAI,KAAK,MAAM,IAAI,SAAS,KAAK,MAAM,IAAI,OAAO,MAAM,KAAK,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;CACxF;CAEF,OAAO;AACT;AAEA,SAAgB,SAAS,QAA0B,OAAgC;CACjF,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,MAAM,OAAO,EAAE,GAAG,KAAK,MAAM,OAAO,EAAE,CAAC;CAC9D,MAAM,CAAC,IAAI,MAAM;CACjB,MAAM,IAAI,OAAO,KAAK,KAAK,KAAK,OAAO,KAAK;CAC5C,OAAO;EACL,MAAM;EACN;EACA;EACA,MAAM;EACN,YAAY,CAAC;EACb,GAAG;EACH,GAAG;EAEH,MAAM,UAAW,QAAQ,IAAI,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM;EAClF,SAAS,UAAU,OAAO,MAAM,IAAI,KAAK,MAAM,QAAQ,MAAM;CAC/D;AACF;;;;;;AASA,SAAgB,cAAc,YAAsB,OAAgC;CAClF,MAAM,IAAI,KAAK,IAAI,GAAG,WAAW,MAAM;CAEvC,OAAO;EAAE,GADK,YAAY,CAAC,KAAM,IAAI,EAAG,GAAG,KAC/B;EAAO,MAAM;EAAY,MAAM,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,IAAI;EAAG;CAAW;AAC3F;;AAGA,SAAgB,cAAc,OAAe,QAAQ,GAAa;CAChE,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,OAAO,MAAM,KAAK,CAAC;CACnD,OAAO;AACT;;;;;AAMA,SAAgB,SAAS,OAAsB;CAC7C,IAAI,MAAM,SAAS,OAAO,OAAO,MAAM,MAAM;CAC7C,MAAM,CAAC,GAAG,KAAK,MAAM;CACrB,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;AACxE"}