@primeui/chart-core 0.0.1-alpha.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/LICENSE +23 -0
- package/README.md +1 -0
- package/dist/animations/index.d.mts +136 -0
- package/dist/animations/index.mjs +18 -0
- package/dist/annotation.utils-Bm0lOO1o.d.mts +290 -0
- package/dist/borderRadius.utils-Cz73LLR_.d.mts +54 -0
- package/dist/canvas-D4vigq47.d.mts +34 -0
- package/dist/canvas.utils-D2WHi2gL.d.mts +167 -0
- package/dist/cartesian/index.d.mts +94 -0
- package/dist/cartesian/index.mjs +93 -0
- package/dist/chunk-22ST6YPP.mjs +304 -0
- package/dist/chunk-2QK2KOBN.mjs +10 -0
- package/dist/chunk-2QRS4YQ5.mjs +18 -0
- package/dist/chunk-3FFJEX4A.mjs +261 -0
- package/dist/chunk-3IYSJ2U7.mjs +567 -0
- package/dist/chunk-3OZLP4I4.mjs +190 -0
- package/dist/chunk-3WEMHXZI.mjs +198 -0
- package/dist/chunk-3Z62EUJN.mjs +138 -0
- package/dist/chunk-4C6EVJ54.mjs +362 -0
- package/dist/chunk-53HW45JB.mjs +102 -0
- package/dist/chunk-55Y3WI6S.mjs +186 -0
- package/dist/chunk-5JCI2DEB.mjs +97 -0
- package/dist/chunk-66T4MRC5.mjs +113 -0
- package/dist/chunk-6HSEJLSR.mjs +376 -0
- package/dist/chunk-6STOLMCA.mjs +187 -0
- package/dist/chunk-7CMVDIOU.mjs +54 -0
- package/dist/chunk-7QQ6ETB4.mjs +228 -0
- package/dist/chunk-A6ZQZFL2.mjs +272 -0
- package/dist/chunk-ADKLH73T.mjs +1 -0
- package/dist/chunk-AGU3NG6D.mjs +22 -0
- package/dist/chunk-AHYIS6EB.mjs +230 -0
- package/dist/chunk-AP3UYWYT.mjs +4 -0
- package/dist/chunk-ARB5T6MP.mjs +326 -0
- package/dist/chunk-ARRGOEFX.mjs +585 -0
- package/dist/chunk-AUF4CHDP.mjs +422 -0
- package/dist/chunk-B4FTADAZ.mjs +561 -0
- package/dist/chunk-BABQKA6K.mjs +339 -0
- package/dist/chunk-BETFQBM2.mjs +197 -0
- package/dist/chunk-BKP26M4K.mjs +413 -0
- package/dist/chunk-BZN2QHGP.mjs +200 -0
- package/dist/chunk-C36VWQ7A.mjs +86 -0
- package/dist/chunk-CHW4RKY3.mjs +16 -0
- package/dist/chunk-CINXJIRR.mjs +120 -0
- package/dist/chunk-DN6AXQYZ.mjs +667 -0
- package/dist/chunk-DP2IZNN3.mjs +92 -0
- package/dist/chunk-DTWTCFRG.mjs +119 -0
- package/dist/chunk-EAMUNLRU.mjs +172 -0
- package/dist/chunk-EDAKJLNA.mjs +17 -0
- package/dist/chunk-ERVQB2VZ.mjs +59 -0
- package/dist/chunk-FFMT6OCO.mjs +92 -0
- package/dist/chunk-FHTC2YDB.mjs +102 -0
- package/dist/chunk-FRST55HY.mjs +16 -0
- package/dist/chunk-HDFGCN2F.mjs +132 -0
- package/dist/chunk-IEGLX7VL.mjs +42 -0
- package/dist/chunk-ILUWFYGY.mjs +220 -0
- package/dist/chunk-IXOWSEHO.mjs +114 -0
- package/dist/chunk-J4RI2C2G.mjs +172 -0
- package/dist/chunk-J65DBT4R.mjs +13 -0
- package/dist/chunk-JGOVWSKH.mjs +179 -0
- package/dist/chunk-JO7VACY2.mjs +25 -0
- package/dist/chunk-JWFBOPM6.mjs +122 -0
- package/dist/chunk-KNDZP446.mjs +895 -0
- package/dist/chunk-KP2TWD4Z.mjs +90 -0
- package/dist/chunk-KQIFO5I3.mjs +225 -0
- package/dist/chunk-KVDEROP6.mjs +59 -0
- package/dist/chunk-LKC7MZKK.mjs +87 -0
- package/dist/chunk-LVMDQ4OJ.mjs +305 -0
- package/dist/chunk-M7B3JF43.mjs +90 -0
- package/dist/chunk-MTGMXRNF.mjs +136 -0
- package/dist/chunk-N3TIT3OH.mjs +1040 -0
- package/dist/chunk-NHRK5KU2.mjs +890 -0
- package/dist/chunk-NKUYIWAP.mjs +243 -0
- package/dist/chunk-NPDZLYIF.mjs +238 -0
- package/dist/chunk-O2X6FF45.mjs +499 -0
- package/dist/chunk-OGJ6IIBW.mjs +176 -0
- package/dist/chunk-OHGCZZPZ.mjs +403 -0
- package/dist/chunk-OWW3K55O.mjs +351 -0
- package/dist/chunk-OXTFAWSK.mjs +60 -0
- package/dist/chunk-PLSDU3C2.mjs +890 -0
- package/dist/chunk-PRDVPOZX.mjs +223 -0
- package/dist/chunk-Q6PPVIHU.mjs +21 -0
- package/dist/chunk-QQBXUDM4.mjs +885 -0
- package/dist/chunk-QS76E3TD.mjs +111 -0
- package/dist/chunk-QWQ6HY4I.mjs +209 -0
- package/dist/chunk-R6Y3R7EW.mjs +135 -0
- package/dist/chunk-RBLZRT5K.mjs +190 -0
- package/dist/chunk-RO4N6YFS.mjs +167 -0
- package/dist/chunk-RQ3CKQOX.mjs +984 -0
- package/dist/chunk-SALTGZFR.mjs +208 -0
- package/dist/chunk-SANZPAJ4.mjs +14 -0
- package/dist/chunk-SDBPQ5CF.mjs +624 -0
- package/dist/chunk-SSLTFJ3U.mjs +364 -0
- package/dist/chunk-SXHVDJGF.mjs +77 -0
- package/dist/chunk-TA4MVAEX.mjs +243 -0
- package/dist/chunk-TAHCOZHF.mjs +1772 -0
- package/dist/chunk-TQ6S34QZ.mjs +152 -0
- package/dist/chunk-UPRXABX5.mjs +90 -0
- package/dist/chunk-VGLSBZDN.mjs +71 -0
- package/dist/chunk-VN7CKCSE.mjs +364 -0
- package/dist/chunk-VVI3OBPJ.mjs +524 -0
- package/dist/chunk-VWF57TS3.mjs +62 -0
- package/dist/chunk-WA3OVISZ.mjs +179 -0
- package/dist/chunk-WCG35U6M.mjs +964 -0
- package/dist/chunk-WFTX4AQJ.mjs +194 -0
- package/dist/chunk-WFVOQ2QZ.mjs +18 -0
- package/dist/chunk-WH3C3Y7P.mjs +149 -0
- package/dist/chunk-WPFUV7K3.mjs +488 -0
- package/dist/chunk-WRULPWHD.mjs +492 -0
- package/dist/chunk-WS64BZXT.mjs +1 -0
- package/dist/chunk-WY4AURRE.mjs +2419 -0
- package/dist/chunk-WYLILAOO.mjs +167 -0
- package/dist/chunk-X4D7FKUS.mjs +62 -0
- package/dist/chunk-X7T34OLW.mjs +139 -0
- package/dist/chunk-XIHBK5D3.mjs +68 -0
- package/dist/chunk-XQQCGFYB.mjs +50 -0
- package/dist/chunk-XTVE4P3L.mjs +214 -0
- package/dist/chunk-XUAASRXW.mjs +579 -0
- package/dist/chunk-Y3L3D4GQ.mjs +685 -0
- package/dist/chunk-YBJ56XJS.mjs +132 -0
- package/dist/chunk-ZQFK6CAE.mjs +1 -0
- package/dist/chunk-ZT2Z7ERM.mjs +874 -0
- package/dist/chunk-ZTL2FQEW.mjs +714 -0
- package/dist/circular/arc/index.d.mts +8 -0
- package/dist/circular/arc/index.mjs +3 -0
- package/dist/circular/index.d.mts +44 -0
- package/dist/circular/index.mjs +13 -0
- package/dist/collect.utils-DiKB4ciO.d.mts +12 -0
- package/dist/computeChartState-BTVIqwyO.d.mts +304 -0
- package/dist/controller-BJE1AZ3q.d.mts +82 -0
- package/dist/controller-BoNigQJr.d.mts +63 -0
- package/dist/controllers/index.d.mts +16 -0
- package/dist/controllers/index.mjs +110 -0
- package/dist/datalabel.utils-CkjGeB8S.d.mts +122 -0
- package/dist/decimation.utils-CcvJVhI4.d.mts +244 -0
- package/dist/geometry-DUUQJXVM.d.mts +60 -0
- package/dist/index-DseIZa1j.d.mts +167 -0
- package/dist/index.d.mts +88 -0
- package/dist/index.mjs +110 -0
- package/dist/orchestrator/index.d.mts +264 -0
- package/dist/orchestrator/index.mjs +33 -0
- package/dist/plugins/index.d.mts +18 -0
- package/dist/plugins/index.mjs +1 -0
- package/dist/property-animations-D433wXzz.d.mts +580 -0
- package/dist/property-store-NORUWFND.d.mts +17 -0
- package/dist/radial/index.d.mts +14 -0
- package/dist/radial/index.mjs +37 -0
- package/dist/renderers/axis/index.d.mts +39 -0
- package/dist/renderers/axis/index.mjs +8 -0
- package/dist/renderers/circular/index.d.mts +13 -0
- package/dist/renderers/circular/index.mjs +13 -0
- package/dist/renderers/index.d.mts +83 -0
- package/dist/renderers/index.mjs +75 -0
- package/dist/renderers/navigator/index.d.mts +103 -0
- package/dist/renderers/navigator/index.mjs +8 -0
- package/dist/resize.utils-D_2qm6rv.d.mts +142 -0
- package/dist/ring.utils-DXvrxMkU.d.mts +138 -0
- package/dist/scale-KFv30jqZ.d.mts +307 -0
- package/dist/scales-Drf8AIhL.d.mts +75 -0
- package/dist/series/bar/canvas/index.d.mts +8 -0
- package/dist/series/bar/canvas/index.mjs +10 -0
- package/dist/series/bar/controller/index.d.mts +105 -0
- package/dist/series/bar/controller/index.mjs +44 -0
- package/dist/series/bar/controller-canvas/index.d.mts +7 -0
- package/dist/series/bar/controller-canvas/index.mjs +49 -0
- package/dist/series/bar/controller-svg/index.d.mts +7 -0
- package/dist/series/bar/controller-svg/index.mjs +49 -0
- package/dist/series/bar/index.d.mts +60 -0
- package/dist/series/bar/index.mjs +13 -0
- package/dist/series/bar/svg/index.d.mts +8 -0
- package/dist/series/bar/svg/index.mjs +11 -0
- package/dist/series/candlestick/canvas/index.d.mts +8 -0
- package/dist/series/candlestick/canvas/index.mjs +8 -0
- package/dist/series/candlestick/controller/index.d.mts +123 -0
- package/dist/series/candlestick/controller/index.mjs +40 -0
- package/dist/series/candlestick/controller-canvas/index.d.mts +7 -0
- package/dist/series/candlestick/controller-canvas/index.mjs +45 -0
- package/dist/series/candlestick/controller-svg/index.d.mts +7 -0
- package/dist/series/candlestick/controller-svg/index.mjs +45 -0
- package/dist/series/candlestick/index.d.mts +11 -0
- package/dist/series/candlestick/index.mjs +10 -0
- package/dist/series/candlestick/svg/index.d.mts +8 -0
- package/dist/series/candlestick/svg/index.mjs +8 -0
- package/dist/series/heatmap/canvas/index.d.mts +16 -0
- package/dist/series/heatmap/canvas/index.mjs +9 -0
- package/dist/series/heatmap/controller/index.d.mts +110 -0
- package/dist/series/heatmap/controller/index.mjs +23 -0
- package/dist/series/heatmap/controller-canvas/index.d.mts +7 -0
- package/dist/series/heatmap/controller-canvas/index.mjs +28 -0
- package/dist/series/heatmap/controller-svg/index.d.mts +7 -0
- package/dist/series/heatmap/controller-svg/index.mjs +28 -0
- package/dist/series/heatmap/index.d.mts +34 -0
- package/dist/series/heatmap/index.mjs +13 -0
- package/dist/series/heatmap/svg/index.d.mts +15 -0
- package/dist/series/heatmap/svg/index.mjs +10 -0
- package/dist/series/line/canvas/index.d.mts +6 -0
- package/dist/series/line/canvas/index.mjs +9 -0
- package/dist/series/line/controller/index.d.mts +111 -0
- package/dist/series/line/controller/index.mjs +47 -0
- package/dist/series/line/controller-canvas/index.d.mts +7 -0
- package/dist/series/line/controller-canvas/index.mjs +54 -0
- package/dist/series/line/controller-svg/index.d.mts +7 -0
- package/dist/series/line/controller-svg/index.mjs +54 -0
- package/dist/series/line/index.d.mts +49 -0
- package/dist/series/line/index.mjs +13 -0
- package/dist/series/line/svg/index.d.mts +6 -0
- package/dist/series/line/svg/index.mjs +9 -0
- package/dist/series/pie/canvas/index.d.mts +8 -0
- package/dist/series/pie/canvas/index.mjs +10 -0
- package/dist/series/pie/controller/index.d.mts +174 -0
- package/dist/series/pie/controller/index.mjs +110 -0
- package/dist/series/pie/controller-canvas/index.d.mts +8 -0
- package/dist/series/pie/controller-canvas/index.mjs +119 -0
- package/dist/series/pie/controller-svg/index.d.mts +8 -0
- package/dist/series/pie/controller-svg/index.mjs +118 -0
- package/dist/series/pie/index.d.mts +59 -0
- package/dist/series/pie/index.mjs +15 -0
- package/dist/series/pie/svg/index.d.mts +6 -0
- package/dist/series/pie/svg/index.mjs +11 -0
- package/dist/series/polar/canvas/index.d.mts +6 -0
- package/dist/series/polar/canvas/index.mjs +7 -0
- package/dist/series/polar/controller/index.d.mts +102 -0
- package/dist/series/polar/controller/index.mjs +46 -0
- package/dist/series/polar/controller-canvas/index.d.mts +8 -0
- package/dist/series/polar/controller-canvas/index.mjs +52 -0
- package/dist/series/polar/controller-svg/index.d.mts +8 -0
- package/dist/series/polar/controller-svg/index.mjs +52 -0
- package/dist/series/polar/index.d.mts +25 -0
- package/dist/series/polar/index.mjs +16 -0
- package/dist/series/polar/svg/index.d.mts +10 -0
- package/dist/series/polar/svg/index.mjs +8 -0
- package/dist/series/radar/canvas/index.d.mts +6 -0
- package/dist/series/radar/canvas/index.mjs +8 -0
- package/dist/series/radar/controller/index.d.mts +121 -0
- package/dist/series/radar/controller/index.mjs +43 -0
- package/dist/series/radar/controller-canvas/index.d.mts +8 -0
- package/dist/series/radar/controller-canvas/index.mjs +51 -0
- package/dist/series/radar/controller-svg/index.d.mts +8 -0
- package/dist/series/radar/controller-svg/index.mjs +51 -0
- package/dist/series/radar/index.d.mts +40 -0
- package/dist/series/radar/index.mjs +13 -0
- package/dist/series/radar/svg/index.d.mts +12 -0
- package/dist/series/radar/svg/index.mjs +9 -0
- package/dist/series/scatter/canvas/index.d.mts +8 -0
- package/dist/series/scatter/canvas/index.mjs +11 -0
- package/dist/series/scatter/controller/index.d.mts +124 -0
- package/dist/series/scatter/controller/index.mjs +44 -0
- package/dist/series/scatter/controller-canvas/index.d.mts +7 -0
- package/dist/series/scatter/controller-canvas/index.mjs +51 -0
- package/dist/series/scatter/controller-svg/index.d.mts +7 -0
- package/dist/series/scatter/controller-svg/index.mjs +51 -0
- package/dist/series/scatter/index.d.mts +25 -0
- package/dist/series/scatter/index.mjs +14 -0
- package/dist/series/scatter/svg/index.d.mts +8 -0
- package/dist/series/scatter/svg/index.mjs +12 -0
- package/dist/series/treemap/canvas/index.d.mts +50 -0
- package/dist/series/treemap/canvas/index.mjs +10 -0
- package/dist/series/treemap/controller/index.d.mts +130 -0
- package/dist/series/treemap/controller/index.mjs +20 -0
- package/dist/series/treemap/controller-canvas/index.d.mts +7 -0
- package/dist/series/treemap/controller-canvas/index.mjs +25 -0
- package/dist/series/treemap/controller-svg/index.d.mts +7 -0
- package/dist/series/treemap/controller-svg/index.mjs +25 -0
- package/dist/series/treemap/index.d.mts +15 -0
- package/dist/series/treemap/index.mjs +12 -0
- package/dist/series/treemap/svg/index.d.mts +15 -0
- package/dist/series/treemap/svg/index.mjs +9 -0
- package/dist/slices-DtewiwJx.d.mts +72 -0
- package/dist/spatialIndex.utils-B_GJkotZ.d.mts +5 -0
- package/dist/squarify.utils-B9CQBpa1.d.mts +50 -0
- package/dist/stacking-CChuAcLN.d.mts +319 -0
- package/dist/streaming.utils-DH-g1gNP.d.mts +49 -0
- package/dist/sync/index.d.mts +130 -0
- package/dist/sync/index.mjs +5 -0
- package/dist/tooltip.renderer-D5wpSlBa.d.mts +210 -0
- package/dist/utils/color/index.d.mts +58 -0
- package/dist/utils/color/index.mjs +4 -0
- package/dist/utils/data/index.d.mts +180 -0
- package/dist/utils/data/index.mjs +7 -0
- package/dist/utils/export/index.d.mts +14 -0
- package/dist/utils/export/index.mjs +6 -0
- package/dist/utils/index.d.mts +49 -0
- package/dist/utils/index.mjs +29 -0
- package/dist/utils/interaction/index.d.mts +255 -0
- package/dist/utils/interaction/index.mjs +9 -0
- package/dist/utils/layout/index.d.mts +3 -0
- package/dist/utils/layout/index.mjs +10 -0
- package/dist/utils/math/index.d.mts +162 -0
- package/dist/utils/math/index.mjs +1 -0
- package/dist/utils/render/index.d.mts +19 -0
- package/dist/utils/render/index.mjs +3 -0
- package/dist/utils/specialized/index.d.mts +37 -0
- package/dist/utils/specialized/index.mjs +66 -0
- package/dist/utils/text/index.d.mts +39 -0
- package/dist/utils/text/index.mjs +8 -0
- package/dist/utils/theme/index.d.mts +295 -0
- package/dist/utils/theme/index.mjs +5 -0
- package/dist/utils/zoom/index.d.mts +90 -0
- package/dist/utils/zoom/index.mjs +3 -0
- package/package.json +56 -0
|
@@ -0,0 +1,890 @@
|
|
|
1
|
+
import { resolveRadarLabels } from './chunk-UPRXABX5.mjs';
|
|
2
|
+
import { resolveSharedRadialGrid } from './chunk-TA4MVAEX.mjs';
|
|
3
|
+
import { calculateRadarLayout, hitTestRadar } from './chunk-A6ZQZFL2.mjs';
|
|
4
|
+
import { renderResolvedLabels } from './chunk-QQBXUDM4.mjs';
|
|
5
|
+
import { AnimatedScene, resolveAnimatedProps, RADAR_ANIMATABLE_PROPS } from './chunk-VN7CKCSE.mjs';
|
|
6
|
+
import { renderCustomMarkersCanvas } from './chunk-ZT2Z7ERM.mjs';
|
|
7
|
+
import { reconcileSvgChildren } from './chunk-KP2TWD4Z.mjs';
|
|
8
|
+
import { parseAnimationConfig } from './chunk-3WEMHXZI.mjs';
|
|
9
|
+
import { cancelRaf, raf } from './chunk-EDAKJLNA.mjs';
|
|
10
|
+
import { buildAccessibilityRenderContext, generateSeriesDescription } from './chunk-OGJ6IIBW.mjs';
|
|
11
|
+
import { collectItems } from './chunk-FFMT6OCO.mjs';
|
|
12
|
+
import { DEFAULT_HOVER_DIM_OPACITY, DEFAULT_HOVER_BRIGHTNESS } from './chunk-NKUYIWAP.mjs';
|
|
13
|
+
import { interpolateRadialGrid } from './chunk-WH3C3Y7P.mjs';
|
|
14
|
+
import { makeItemContext, defaultLightTheme, resolveSwatchColor, getPrimaryColor, getDefaultColor, FIELD_DEFAULTS } from './chunk-O2X6FF45.mjs';
|
|
15
|
+
import { setAttr, createSvgGroup, materializeSvgNode } from './chunk-SSLTFJ3U.mjs';
|
|
16
|
+
import { calculateNiceDomain } from './chunk-RQ3CKQOX.mjs';
|
|
17
|
+
|
|
18
|
+
// src/series/radar/controller/helpers.ts
|
|
19
|
+
function buildRadarFingerprint(layout, entries) {
|
|
20
|
+
const parts = [];
|
|
21
|
+
for (const sd of layout.series) {
|
|
22
|
+
const dsEntry = entries.find((e) => e.id === sd.id);
|
|
23
|
+
const visible = dsEntry?.visible ?? sd.visible;
|
|
24
|
+
const ptHash = sd.points.map((p2) => `${p2.categoryIndex}:${p2.value}:${Math.round(p2.x)}:${Math.round(p2.y)}`).join(",");
|
|
25
|
+
const p = dsEntry?.props;
|
|
26
|
+
const visualHash = `sm:${p?.showMarkers}|fo:${p?.fillOpacity}|lw:${p?.lineStrokeWidth}|ls:${p?.lineStyle}|cv:${p?.curve}|c:${sd.color}`;
|
|
27
|
+
parts.push(`${sd.id}|v:${visible}|${visualHash}|${ptHash}`);
|
|
28
|
+
}
|
|
29
|
+
parts.push(`dom:${layout.domain[0]},${layout.domain[1]}`);
|
|
30
|
+
parts.push(`r:${Math.round(layout.radius)}`);
|
|
31
|
+
const g = layout.grid;
|
|
32
|
+
parts.push(`grid:${g.shape}|${g.levels}|${g.color}|${g.opacity}|${g.width}|${g.style}`);
|
|
33
|
+
return parts.join("||");
|
|
34
|
+
}
|
|
35
|
+
function lerpSeriesFade(fade, now) {
|
|
36
|
+
if (fade.startTime === -1) {
|
|
37
|
+
return { fillOpacity: fade.fromFillOpacity, lineStrokeWidth: fade.fromLineStrokeWidth };
|
|
38
|
+
}
|
|
39
|
+
const elapsed = now - fade.startTime;
|
|
40
|
+
const raw = Math.max(0, Math.min(1, elapsed / Math.max(1, fade.duration)));
|
|
41
|
+
const p = fade.easing(raw);
|
|
42
|
+
return {
|
|
43
|
+
fillOpacity: fade.fromFillOpacity + (fade.toFillOpacity - fade.fromFillOpacity) * p,
|
|
44
|
+
lineStrokeWidth: fade.fromLineStrokeWidth + (fade.toLineStrokeWidth - fade.fromLineStrokeWidth) * p
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function mergeRadarPropsWithOverrides(overrides, baseProps) {
|
|
48
|
+
if (!overrides || !baseProps) return baseProps;
|
|
49
|
+
return { ...baseProps, ...overrides };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/series/radar/controller/types.ts
|
|
53
|
+
var RADAR_POINT_REGISTRY = {
|
|
54
|
+
number: ["x", "y", "value", "baseX", "baseY", "baseValue"],
|
|
55
|
+
color: []
|
|
56
|
+
};
|
|
57
|
+
function pointKey(seriesId, categoryIndex) {
|
|
58
|
+
return `${seriesId}::${categoryIndex}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/series/radar/controller/paint.ts
|
|
62
|
+
function buildRadarSvgChildren(ctx, layout, entries, input) {
|
|
63
|
+
const children = [];
|
|
64
|
+
const context = input.chartId ? { chartId: input.chartId } : void 0;
|
|
65
|
+
const a11y = buildAccessibilityRenderContext(input.features);
|
|
66
|
+
for (let si = 0; si < layout.series.length; si++) {
|
|
67
|
+
const ds = entries[si];
|
|
68
|
+
const mergedProps = ds ? mergeRadarPropsWithOverrides(ctx._propertyOverrides.get(ds.id), ds.props) : void 0;
|
|
69
|
+
const node = ctx._paint.renderSvg(layout, si, ctx.hoverState, input.theme, ctx.effectConfig, mergedProps, void 0, context);
|
|
70
|
+
const sd = layout.series[si];
|
|
71
|
+
if (sd) setAttr(node, "data-dataset", sd.id);
|
|
72
|
+
if (sd && a11y?.enabled && a11y.landmarkVerbosity === "all") {
|
|
73
|
+
setAttr(node, "role", "region");
|
|
74
|
+
setAttr(node, "aria-label", generateSeriesDescription(mergedProps?.name ?? sd.id, "radar", sd.points.length));
|
|
75
|
+
}
|
|
76
|
+
children.push(node);
|
|
77
|
+
}
|
|
78
|
+
const lc = input.labelConfig;
|
|
79
|
+
if (lc) {
|
|
80
|
+
for (let si = 0; si < layout.series.length; si++) {
|
|
81
|
+
const sd = layout.series[si];
|
|
82
|
+
const ds = entries[si];
|
|
83
|
+
if (!sd.visible || !ds) continue;
|
|
84
|
+
const dsTotal = sd.points.reduce((sum, pt) => sum + Math.abs(pt.value), 0);
|
|
85
|
+
const labels = resolveRadarLabels(sd.points, layout.categories, sd.color ?? getDefaultColor(sd.seriesIdx, input.theme), dsTotal, layout.center, lc, ds.props.data);
|
|
86
|
+
const labelNode = createSvgGroup();
|
|
87
|
+
renderResolvedLabels(labels, lc, { renderer: "svg", svgGroup: labelNode, theme: input.theme });
|
|
88
|
+
setAttr(labelNode, "data-layer", `labels-${sd.id}`);
|
|
89
|
+
children.push(labelNode);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return children;
|
|
93
|
+
}
|
|
94
|
+
function renderToSvg(ctx, group, layout, entries, input) {
|
|
95
|
+
group.replaceChildren(...buildRadarSvgChildren(ctx, layout, entries, input).map(materializeSvgNode));
|
|
96
|
+
}
|
|
97
|
+
function renderCanvasContent(ctx, c2d) {
|
|
98
|
+
const layout = ctx.lastRenderedLayout ?? ctx._layout;
|
|
99
|
+
if (!layout || ctx._entries.length === 0) return;
|
|
100
|
+
for (let si = 0; si < layout.series.length; si++) {
|
|
101
|
+
const ds = ctx._entries[si];
|
|
102
|
+
const mergedProps = ds ? mergeRadarPropsWithOverrides(ctx._propertyOverrides.get(ds.id), ds.props) : void 0;
|
|
103
|
+
ctx._paint.renderCanvas(c2d, layout, si, ctx.hoverState, ctx.effectConfig, mergedProps, ctx.lastInput?.theme ?? defaultLightTheme);
|
|
104
|
+
}
|
|
105
|
+
const markerEntries = [];
|
|
106
|
+
for (let si = 0; si < layout.series.length; si++) {
|
|
107
|
+
const ds = ctx._entries[si];
|
|
108
|
+
const sd = layout.series[si];
|
|
109
|
+
if (!ds || !sd.visible) continue;
|
|
110
|
+
const renderMarkerFn = ds.props.renderMarker;
|
|
111
|
+
if (!renderMarkerFn) continue;
|
|
112
|
+
const mergedProps = mergeRadarPropsWithOverrides(ctx._propertyOverrides.get(ds.id), ds.props) ?? ds.props;
|
|
113
|
+
markerEntries.push({
|
|
114
|
+
dsId: ds.id,
|
|
115
|
+
renderMarker: renderMarkerFn,
|
|
116
|
+
visiblePoints: sd.points.map((pt, pi) => ({ x: pt.x, y: pt.y, dataIndex: pi, value: pt.value, category: layout.categories[pt.categoryIndex] })),
|
|
117
|
+
data: ds.props.data,
|
|
118
|
+
color: sd.color ?? getDefaultColor(sd.seriesIdx, ctx.lastInput?.theme ?? defaultLightTheme),
|
|
119
|
+
markerSize: typeof mergedProps.markerSize === "number" ? mergedProps.markerSize : 4,
|
|
120
|
+
effects: { dimOpacity: ctx.effectConfig.dimOpacity }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (markerEntries.length > 0) {
|
|
124
|
+
renderCustomMarkersCanvas(c2d, markerEntries, ctx.hoverState);
|
|
125
|
+
}
|
|
126
|
+
const lc = ctx.lastInput?.labelConfig;
|
|
127
|
+
if (lc) {
|
|
128
|
+
for (let si = 0; si < layout.series.length; si++) {
|
|
129
|
+
const sd = layout.series[si];
|
|
130
|
+
const ds = ctx._entries[si];
|
|
131
|
+
if (!sd.visible || !ds) continue;
|
|
132
|
+
const dsTotal = sd.points.reduce((sum, pt) => sum + Math.abs(pt.value), 0);
|
|
133
|
+
const labels = resolveRadarLabels(sd.points, layout.categories, sd.color ?? getDefaultColor(sd.seriesIdx, ctx.lastInput?.theme ?? defaultLightTheme), dsTotal, layout.center, lc, ds.props.data);
|
|
134
|
+
renderResolvedLabels(labels, lc, { renderer: "canvas", ctx: c2d, theme: ctx.lastInput?.theme ?? defaultLightTheme });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/series/radar/controller/scene.ts
|
|
140
|
+
function fullReset(ctx) {
|
|
141
|
+
ctx._layout = null;
|
|
142
|
+
ctx.lastRenderedLayout = null;
|
|
143
|
+
setMarkerData(ctx, null);
|
|
144
|
+
if (ctx._animRafId !== null) {
|
|
145
|
+
cancelRaf(ctx._animRafId);
|
|
146
|
+
ctx._animRafId = null;
|
|
147
|
+
}
|
|
148
|
+
ctx._scene.reset();
|
|
149
|
+
ctx._seriesFades.clear();
|
|
150
|
+
ctx._seriesSettledStyle.clear();
|
|
151
|
+
ctx._gridLerp = null;
|
|
152
|
+
ctx._lastSettledDomain = null;
|
|
153
|
+
ctx._lastFingerprint = "";
|
|
154
|
+
ctx._firstRender = true;
|
|
155
|
+
ctx._propertyOverrides.clear();
|
|
156
|
+
}
|
|
157
|
+
function runAllHidden(ctx, features) {
|
|
158
|
+
const liveCount = ctx._scene.getElements().length;
|
|
159
|
+
const hasFades = ctx._seriesFades.size > 0;
|
|
160
|
+
if (liveCount === 0 && !hasFades) {
|
|
161
|
+
ctx._layout = null;
|
|
162
|
+
ctx.lastRenderedLayout = null;
|
|
163
|
+
setMarkerData(ctx, null);
|
|
164
|
+
if (ctx._animRafId !== null) {
|
|
165
|
+
cancelRaf(ctx._animRafId);
|
|
166
|
+
ctx._animRafId = null;
|
|
167
|
+
}
|
|
168
|
+
ctx._gridLerp = null;
|
|
169
|
+
ctx._lastFingerprint = "|EMPTY";
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const animConfig = features.get("animation")?.props;
|
|
173
|
+
const { enabled: animEnabled, duration, easing } = parseAnimationConfig(animConfig);
|
|
174
|
+
const shouldAnimate = animEnabled && duration > 0;
|
|
175
|
+
const fingerprint = "|EMPTY";
|
|
176
|
+
if (fingerprint === ctx._lastFingerprint) {
|
|
177
|
+
if (ctx._animRafId !== null) return;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
ctx._lastFingerprint = fingerprint;
|
|
181
|
+
if (ctx._animRafId !== null) {
|
|
182
|
+
cancelRaf(ctx._animRafId);
|
|
183
|
+
ctx._animRafId = null;
|
|
184
|
+
}
|
|
185
|
+
const opts = { numbers: { duration: shouldAnimate ? duration : 0, easing } };
|
|
186
|
+
ctx._scene.diff(/* @__PURE__ */ new Map(), opts);
|
|
187
|
+
const now = performance.now();
|
|
188
|
+
for (const [seriesId, settled] of ctx._seriesSettledStyle) {
|
|
189
|
+
if (settled.fillOpacity <= 1e-3 && settled.lineStrokeWidth <= 1e-3) continue;
|
|
190
|
+
let fromFill = settled.fillOpacity;
|
|
191
|
+
let fromStroke = settled.lineStrokeWidth;
|
|
192
|
+
const existing = ctx._seriesFades.get(seriesId);
|
|
193
|
+
if (existing) {
|
|
194
|
+
const lerped = lerpSeriesFade(existing, now);
|
|
195
|
+
fromFill = lerped.fillOpacity;
|
|
196
|
+
fromStroke = lerped.lineStrokeWidth;
|
|
197
|
+
}
|
|
198
|
+
ctx._seriesFades.set(seriesId, {
|
|
199
|
+
fromFillOpacity: fromFill,
|
|
200
|
+
toFillOpacity: 0,
|
|
201
|
+
fromLineStrokeWidth: fromStroke,
|
|
202
|
+
toLineStrokeWidth: 0,
|
|
203
|
+
startTime: -1,
|
|
204
|
+
duration: shouldAnimate ? duration : 0,
|
|
205
|
+
easing
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
ctx._gridLerp = null;
|
|
209
|
+
if (shouldAnimate) {
|
|
210
|
+
renderSceneFrame(ctx);
|
|
211
|
+
startAnimLoop(ctx);
|
|
212
|
+
} else {
|
|
213
|
+
ctx._scene.tick(performance.now());
|
|
214
|
+
if (ctx._scene.getElements().length === 0) {
|
|
215
|
+
ctx._layout = null;
|
|
216
|
+
setMarkerData(ctx, null);
|
|
217
|
+
}
|
|
218
|
+
ctx._seriesFades.clear();
|
|
219
|
+
renderSceneFrame(ctx);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function updateGridLerp(ctx, targetLayout, shouldAnimate, duration, easing, tickCount) {
|
|
223
|
+
const isPerSpoke = !!targetLayout.perSpokeDomains && targetLayout.perSpokeDomains.size > 0;
|
|
224
|
+
let targetDomain;
|
|
225
|
+
let targetGrid;
|
|
226
|
+
if (isPerSpoke) {
|
|
227
|
+
targetDomain = targetLayout.domain;
|
|
228
|
+
targetGrid = targetLayout.grid;
|
|
229
|
+
} else {
|
|
230
|
+
const resolved = resolveSharedRadialGrid(targetLayout.grid, targetLayout.domain, targetLayout.rawDataMax, targetLayout.radius, tickCount);
|
|
231
|
+
targetDomain = resolved.domain;
|
|
232
|
+
targetGrid = { ...targetLayout.grid, levels: resolved.levelValues.length, levelValues: resolved.levelValues, levelRadii: resolved.levelRadii };
|
|
233
|
+
}
|
|
234
|
+
const prevSettled = ctx._lastSettledDomain;
|
|
235
|
+
const domainChanged = !prevSettled || prevSettled[0] !== targetDomain[0] || prevSettled[1] !== targetDomain[1];
|
|
236
|
+
if (shouldAnimate && domainChanged && prevSettled) {
|
|
237
|
+
const fromDomain = ctx._gridLerp ? currentGridDomain(ctx) : prevSettled;
|
|
238
|
+
ctx._gridLerp = {
|
|
239
|
+
fromDomain,
|
|
240
|
+
toDomain: targetDomain,
|
|
241
|
+
targetGrid,
|
|
242
|
+
targetRadius: targetLayout.radius,
|
|
243
|
+
startTime: -1,
|
|
244
|
+
duration,
|
|
245
|
+
easing
|
|
246
|
+
};
|
|
247
|
+
} else {
|
|
248
|
+
ctx._gridLerp = null;
|
|
249
|
+
ctx._lastSettledDomain = targetDomain;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function currentGridDomain(ctx) {
|
|
253
|
+
if (!ctx._gridLerp) return ctx._lastSettledDomain ?? [0, 0];
|
|
254
|
+
const { fromDomain, toDomain, startTime, duration, easing } = ctx._gridLerp;
|
|
255
|
+
if (startTime === -1) return fromDomain;
|
|
256
|
+
const elapsed = performance.now() - startTime;
|
|
257
|
+
const raw = Math.max(0, Math.min(1, elapsed / duration));
|
|
258
|
+
const p = easing(raw);
|
|
259
|
+
return [fromDomain[0] + (toDomain[0] - fromDomain[0]) * p, fromDomain[1] + (toDomain[1] - fromDomain[1]) * p];
|
|
260
|
+
}
|
|
261
|
+
function buildLayoutFromScene(ctx, now) {
|
|
262
|
+
if (!ctx._layout) return null;
|
|
263
|
+
const elementsBySeries = /* @__PURE__ */ new Map();
|
|
264
|
+
for (const el of ctx._scene.getElements()) {
|
|
265
|
+
const s = el.current;
|
|
266
|
+
const list = elementsBySeries.get(s.seriesId);
|
|
267
|
+
if (list) list.push(s);
|
|
268
|
+
else elementsBySeries.set(s.seriesId, [s]);
|
|
269
|
+
}
|
|
270
|
+
const series = [];
|
|
271
|
+
for (const targetSd of ctx._layout.series) {
|
|
272
|
+
const stateList = elementsBySeries.get(targetSd.id);
|
|
273
|
+
if (!stateList || stateList.length === 0) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
stateList.sort((a, b) => a.categoryIndex - b.categoryIndex);
|
|
277
|
+
const points = stateList.map((s) => ({
|
|
278
|
+
x: s.x,
|
|
279
|
+
y: s.y,
|
|
280
|
+
value: s.value,
|
|
281
|
+
angle: s.angle,
|
|
282
|
+
categoryIndex: s.categoryIndex
|
|
283
|
+
}));
|
|
284
|
+
const basePoints = stateList[0].hasBase ? stateList.map((s) => ({
|
|
285
|
+
x: s.baseX,
|
|
286
|
+
y: s.baseY,
|
|
287
|
+
value: s.baseValue,
|
|
288
|
+
angle: s.angle,
|
|
289
|
+
categoryIndex: s.categoryIndex
|
|
290
|
+
})) : void 0;
|
|
291
|
+
let fillOpacity = targetSd.fillOpacity;
|
|
292
|
+
let lineStrokeWidth = targetSd.lineStrokeWidth;
|
|
293
|
+
const fade = ctx._seriesFades.get(targetSd.id);
|
|
294
|
+
if (fade) {
|
|
295
|
+
if (fade.startTime === -1) fade.startTime = now;
|
|
296
|
+
const lerped = lerpSeriesFade(fade, now);
|
|
297
|
+
fillOpacity = lerped.fillOpacity;
|
|
298
|
+
lineStrokeWidth = lerped.lineStrokeWidth;
|
|
299
|
+
} else if (!targetSd.visible) {
|
|
300
|
+
const settled = ctx._seriesSettledStyle.get(targetSd.id);
|
|
301
|
+
if (settled) {
|
|
302
|
+
fillOpacity = settled.fillOpacity;
|
|
303
|
+
lineStrokeWidth = settled.lineStrokeWidth;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const overrides = ctx._propertyOverrides.get(targetSd.id);
|
|
307
|
+
if (overrides) {
|
|
308
|
+
if (typeof overrides.fillOpacity === "number") fillOpacity = overrides.fillOpacity;
|
|
309
|
+
if (typeof overrides.lineStrokeWidth === "number") lineStrokeWidth = overrides.lineStrokeWidth;
|
|
310
|
+
}
|
|
311
|
+
series.push({
|
|
312
|
+
...targetSd,
|
|
313
|
+
points,
|
|
314
|
+
basePoints,
|
|
315
|
+
visible: true,
|
|
316
|
+
// keep drawn during exit; opacity carries the fade
|
|
317
|
+
fillOpacity,
|
|
318
|
+
lineStrokeWidth
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
let grid = ctx._layout.grid;
|
|
322
|
+
let gridAnimating = false;
|
|
323
|
+
if (ctx._gridLerp) {
|
|
324
|
+
if (ctx._gridLerp.startTime === -1) ctx._gridLerp.startTime = now;
|
|
325
|
+
const elapsed = now - ctx._gridLerp.startTime;
|
|
326
|
+
const raw = Math.max(0, Math.min(1, elapsed / ctx._gridLerp.duration));
|
|
327
|
+
const p = ctx._gridLerp.easing(raw);
|
|
328
|
+
grid = interpolateRadialGrid(ctx._gridLerp.fromDomain, ctx._gridLerp.toDomain, ctx._gridLerp.targetGrid, ctx._gridLerp.targetRadius, p);
|
|
329
|
+
gridAnimating = true;
|
|
330
|
+
if (raw >= 1) {
|
|
331
|
+
ctx._lastSettledDomain = ctx._gridLerp.toDomain;
|
|
332
|
+
ctx._gridLerp = null;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return { ...ctx._layout, series, grid, gridAnimating };
|
|
336
|
+
}
|
|
337
|
+
function renderSceneFrame(ctx) {
|
|
338
|
+
const layout = buildLayoutFromScene(ctx, performance.now());
|
|
339
|
+
if (!layout || !ctx.lastInput) return;
|
|
340
|
+
ctx.lastRenderedLayout = layout;
|
|
341
|
+
setMarkerData(ctx, { layout, entries: ctx._entries });
|
|
342
|
+
if (ctx.lastInput.renderer === "svg" && ctx.svgGroup) {
|
|
343
|
+
renderToSvg(ctx, ctx.svgGroup, layout, ctx._entries, ctx.lastInput);
|
|
344
|
+
} else if (ctx.lastInput.renderer === "canvas") {
|
|
345
|
+
ctx.lastInput.requestRedraw?.();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function startAnimLoop(ctx) {
|
|
349
|
+
if (ctx._animRafId !== null) {
|
|
350
|
+
cancelRaf(ctx._animRafId);
|
|
351
|
+
}
|
|
352
|
+
const tick = (now) => {
|
|
353
|
+
ctx._animRafId = null;
|
|
354
|
+
const { allIdle } = ctx._scene.tick(now);
|
|
355
|
+
for (const [seriesId, fade] of [...ctx._seriesFades]) {
|
|
356
|
+
if (fade.startTime === -1) continue;
|
|
357
|
+
const elapsed = now - fade.startTime;
|
|
358
|
+
const raw = elapsed / Math.max(1, fade.duration);
|
|
359
|
+
if (raw >= 1) {
|
|
360
|
+
ctx._seriesSettledStyle.set(seriesId, {
|
|
361
|
+
fillOpacity: fade.toFillOpacity,
|
|
362
|
+
lineStrokeWidth: fade.toLineStrokeWidth
|
|
363
|
+
});
|
|
364
|
+
ctx._seriesFades.delete(seriesId);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
renderSceneFrame(ctx);
|
|
368
|
+
ctx.onFrame?.();
|
|
369
|
+
const fadesActive = ctx._seriesFades.size > 0;
|
|
370
|
+
if (!allIdle || ctx._gridLerp !== null || fadesActive) {
|
|
371
|
+
ctx._animRafId = raf(tick);
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
ctx._animRafId = raf(tick);
|
|
375
|
+
}
|
|
376
|
+
function setMarkerData(ctx, data) {
|
|
377
|
+
ctx._markerData = data;
|
|
378
|
+
ctx.onMarkerDataChange?.(data);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// src/series/radar/controller/index.ts
|
|
382
|
+
function buildPerAxisDomains(entries, yAxes) {
|
|
383
|
+
if (!yAxes || yAxes.size === 0) return void 0;
|
|
384
|
+
const result = /* @__PURE__ */ new Map();
|
|
385
|
+
for (const [axisId, axis] of yAxes) {
|
|
386
|
+
const rawMin = axis.props.min;
|
|
387
|
+
const rawMax = axis.props.max;
|
|
388
|
+
const explicitMin = typeof rawMin === "number" ? rawMin : void 0;
|
|
389
|
+
const explicitMax = typeof rawMax === "number" ? rawMax : void 0;
|
|
390
|
+
const axisValues = [];
|
|
391
|
+
for (const ds of entries) {
|
|
392
|
+
if (!ds.visible) continue;
|
|
393
|
+
if (ds.props.yAxisId !== axisId) continue;
|
|
394
|
+
const data = ds.props.data;
|
|
395
|
+
const valueField = ds.props.valueField ?? FIELD_DEFAULTS.valueField;
|
|
396
|
+
if (!data || !valueField) continue;
|
|
397
|
+
for (let i = 0; i < data.length; i++) {
|
|
398
|
+
const item = data[i];
|
|
399
|
+
const v = typeof valueField === "function" ? valueField(makeItemContext(item, i)) : item[valueField];
|
|
400
|
+
if (typeof v === "number" && isFinite(v)) axisValues.push(v);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
let domainMin;
|
|
404
|
+
let domainMax;
|
|
405
|
+
if (explicitMin !== void 0 && explicitMax !== void 0) {
|
|
406
|
+
domainMin = explicitMin;
|
|
407
|
+
domainMax = explicitMax;
|
|
408
|
+
} else {
|
|
409
|
+
const auto = axisValues.length ? calculateNiceDomain(axisValues, { includeZero: true, nice: true }) : [0, 1];
|
|
410
|
+
domainMin = explicitMin ?? auto[0];
|
|
411
|
+
domainMax = explicitMax ?? auto[1];
|
|
412
|
+
}
|
|
413
|
+
result.set(axisId, [domainMin, domainMax]);
|
|
414
|
+
}
|
|
415
|
+
return result.size ? result : void 0;
|
|
416
|
+
}
|
|
417
|
+
function buildPerSpokeDomains(entries, yAxes, categories, isStacked) {
|
|
418
|
+
if (!yAxes || yAxes.size === 0 || categories.length === 0) return void 0;
|
|
419
|
+
const yAxisByCategory = /* @__PURE__ */ new Map();
|
|
420
|
+
for (const axis of yAxes.values()) {
|
|
421
|
+
const cat = axis.props.category;
|
|
422
|
+
if (typeof cat === "string" && cat.length > 0) yAxisByCategory.set(cat, axis);
|
|
423
|
+
}
|
|
424
|
+
if (yAxisByCategory.size === 0) return void 0;
|
|
425
|
+
const valuesPerSpoke = categories.map(() => []);
|
|
426
|
+
if (isStacked) {
|
|
427
|
+
const stackedPerSpoke = new Array(categories.length).fill(0);
|
|
428
|
+
for (const ds of entries) {
|
|
429
|
+
if (!ds.visible) continue;
|
|
430
|
+
const data = ds.props.data;
|
|
431
|
+
const valueField = ds.props.valueField ?? FIELD_DEFAULTS.valueField;
|
|
432
|
+
const categoryField = ds.props.categoryField ?? FIELD_DEFAULTS.categoryField;
|
|
433
|
+
if (!data || !valueField || !categoryField) continue;
|
|
434
|
+
for (let i = 0; i < data.length; i++) {
|
|
435
|
+
const item = data[i];
|
|
436
|
+
const cat = typeof categoryField === "function" ? categoryField(makeItemContext(item, i)) : item[categoryField];
|
|
437
|
+
const v = typeof valueField === "function" ? valueField(makeItemContext(item, i)) : item[valueField];
|
|
438
|
+
const ci = categories.indexOf(cat);
|
|
439
|
+
if (ci < 0) continue;
|
|
440
|
+
if (typeof v !== "number" || !isFinite(v)) continue;
|
|
441
|
+
stackedPerSpoke[ci] += v;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
for (let ci = 0; ci < categories.length; ci++) valuesPerSpoke[ci].push(stackedPerSpoke[ci]);
|
|
445
|
+
} else {
|
|
446
|
+
for (const ds of entries) {
|
|
447
|
+
if (!ds.visible) continue;
|
|
448
|
+
const data = ds.props.data;
|
|
449
|
+
const valueField = ds.props.valueField ?? FIELD_DEFAULTS.valueField;
|
|
450
|
+
const categoryField = ds.props.categoryField ?? FIELD_DEFAULTS.categoryField;
|
|
451
|
+
if (!data || !valueField || !categoryField) continue;
|
|
452
|
+
for (let i = 0; i < data.length; i++) {
|
|
453
|
+
const item = data[i];
|
|
454
|
+
const cat = typeof categoryField === "function" ? categoryField(makeItemContext(item, i)) : item[categoryField];
|
|
455
|
+
const v = typeof valueField === "function" ? valueField(makeItemContext(item, i)) : item[valueField];
|
|
456
|
+
const ci = categories.indexOf(cat);
|
|
457
|
+
if (ci < 0) continue;
|
|
458
|
+
if (typeof v !== "number" || !isFinite(v)) continue;
|
|
459
|
+
valuesPerSpoke[ci].push(v);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
const result = /* @__PURE__ */ new Map();
|
|
464
|
+
for (let ci = 0; ci < categories.length; ci++) {
|
|
465
|
+
const declared = yAxisByCategory.get(categories[ci]);
|
|
466
|
+
const rawMin = declared ? declared.props.min : void 0;
|
|
467
|
+
const rawMax = declared ? declared.props.max : void 0;
|
|
468
|
+
const explicitMin = typeof rawMin === "number" ? rawMin : void 0;
|
|
469
|
+
const explicitMax = typeof rawMax === "number" ? rawMax : void 0;
|
|
470
|
+
let domainMin;
|
|
471
|
+
let domainMax;
|
|
472
|
+
if (explicitMin !== void 0 && explicitMax !== void 0) {
|
|
473
|
+
domainMin = explicitMin;
|
|
474
|
+
domainMax = explicitMax;
|
|
475
|
+
} else {
|
|
476
|
+
const auto = valuesPerSpoke[ci].length ? calculateNiceDomain(valuesPerSpoke[ci], { includeZero: true, nice: true }) : [0, 1];
|
|
477
|
+
domainMin = explicitMin ?? auto[0];
|
|
478
|
+
domainMax = explicitMax ?? auto[1];
|
|
479
|
+
}
|
|
480
|
+
result.set(ci, [domainMin, domainMax]);
|
|
481
|
+
}
|
|
482
|
+
return result;
|
|
483
|
+
}
|
|
484
|
+
var RadarRendererController = class {
|
|
485
|
+
constructor(paint) {
|
|
486
|
+
this._animRafId = null;
|
|
487
|
+
this._lastFingerprint = "";
|
|
488
|
+
/**
|
|
489
|
+
* Per-dataset property-animation overrides resolved from AnimatedPropertyStore.
|
|
490
|
+
* Set by `applyPropertyAnimations()` each property-animation tick and merged
|
|
491
|
+
* into the rendered output at two places:
|
|
492
|
+
* - `_buildLayoutFromScene` — fields that live on RadarSeriesData
|
|
493
|
+
* (fillOpacity, lineStrokeWidth) get merged into the per-frame layout.
|
|
494
|
+
* - `renderToSvg` / `renderCanvasContent` / `applyHover` — fields that
|
|
495
|
+
* the renderers read directly from `ds.props` (markerSize,
|
|
496
|
+
* borderStrokeWidth, lineDashOffset, opacity, tension) get spread onto
|
|
497
|
+
* a shim props object passed to the radar renderers.
|
|
498
|
+
*
|
|
499
|
+
* Tension note: radar's SVG children are rebuilt from the descriptor tree on
|
|
500
|
+
* every `_renderSceneFrame` — a full render goes through
|
|
501
|
+
* `replaceChildren(...buildRadarSvgChildren(...).map(materializeSvgNode))`,
|
|
502
|
+
* while hover diffs the same descriptors through `reconcileSvgChildren`. Either
|
|
503
|
+
* way the path `d` attribute is recomputed from the rebuilt descriptors when
|
|
504
|
+
* `tension` changes — no surgical `setAttribute('d', …)` patching is needed
|
|
505
|
+
* (unlike Line, whose SVG DOM is segmented per-dataset and patched in-place).
|
|
506
|
+
*/
|
|
507
|
+
this._propertyOverrides = /* @__PURE__ */ new Map();
|
|
508
|
+
// First-render flag: lets emptyState collapse to center on first diff (matches
|
|
509
|
+
// createRadarEntranceLayout). After first diff, emptyState collapses to base
|
|
510
|
+
// (matches toggle-on "ring inflates from base").
|
|
511
|
+
this._firstRender = true;
|
|
512
|
+
// Captured before each diff() so the emptyState closure can read center.
|
|
513
|
+
this._activeCenter = { x: 0, y: 0 };
|
|
514
|
+
// Per-series opacity fade for stacked enter/exit. Non-stacked series don't fade.
|
|
515
|
+
this._seriesFades = /* @__PURE__ */ new Map();
|
|
516
|
+
// Last settled (non-fading) per-series fill/stroke values. Used as the
|
|
517
|
+
// starting point for the next fade.
|
|
518
|
+
this._seriesSettledStyle = /* @__PURE__ */ new Map();
|
|
519
|
+
// Grid lerp (radial axis rings + tick labels).
|
|
520
|
+
this._gridLerp = null;
|
|
521
|
+
this._lastSettledDomain = null;
|
|
522
|
+
// Target layout (reference; bars/points come from the scene per-frame).
|
|
523
|
+
this._layout = null;
|
|
524
|
+
// Last frame's rendered layout (read by hover repaint, hit-testing, grid consumers).
|
|
525
|
+
this.lastRenderedLayout = null;
|
|
526
|
+
this._entries = [];
|
|
527
|
+
this.hoverState = { datasetId: null, index: null };
|
|
528
|
+
this.effectConfig = { hoverBrightness: 1, dimOpacity: 1 };
|
|
529
|
+
this.lastInput = null;
|
|
530
|
+
this.svgGroup = null;
|
|
531
|
+
this._hasRadarDatasets = false;
|
|
532
|
+
this._markerData = null;
|
|
533
|
+
this.onFrame = null;
|
|
534
|
+
this.onMarkerDataChange = null;
|
|
535
|
+
this._paint = paint;
|
|
536
|
+
this._scene = new AnimatedScene({
|
|
537
|
+
// ENTER: on the very first diff, collapse outer + base both to center
|
|
538
|
+
// (matches createRadarEntranceLayout's "all points at center, value=0").
|
|
539
|
+
// After the first diff, collapse outer to base (matches toggle-on
|
|
540
|
+
// "stacked ring inflates from base"; non-stacked has baseX=center.x).
|
|
541
|
+
emptyState: (target) => {
|
|
542
|
+
if (this._firstRender) {
|
|
543
|
+
return {
|
|
544
|
+
...target,
|
|
545
|
+
x: this._activeCenter.x,
|
|
546
|
+
y: this._activeCenter.y,
|
|
547
|
+
value: 0,
|
|
548
|
+
baseX: this._activeCenter.x,
|
|
549
|
+
baseY: this._activeCenter.y,
|
|
550
|
+
baseValue: 0
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
return { ...target, x: target.baseX, y: target.baseY, value: 0 };
|
|
554
|
+
},
|
|
555
|
+
// EXIT: collapse outer to base. For stacked this is the inner ring boundary;
|
|
556
|
+
// for non-stacked, baseX/baseY === center.x/center.y so collapse → center.
|
|
557
|
+
exitEmptyState: (target) => ({ ...target, x: target.baseX, y: target.baseY, value: 0 }),
|
|
558
|
+
registry: RADAR_POINT_REGISTRY
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
// ================================================================
|
|
562
|
+
// PUBLIC API
|
|
563
|
+
// ================================================================
|
|
564
|
+
update(input) {
|
|
565
|
+
this.lastInput = input;
|
|
566
|
+
this.svgGroup = input.svgGroup ?? null;
|
|
567
|
+
const { datasets, datasetVisibility, chartArea, features, globalFont, sharedContext, yAxes } = input;
|
|
568
|
+
this._hasRadarDatasets = Array.from(datasets.values()).some((ds) => ds.type === "radar");
|
|
569
|
+
if (!this._hasRadarDatasets) {
|
|
570
|
+
this._fullReset();
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
const sortedDatasets = Array.from(datasets.entries()).sort(([, a], [, b]) => a.order - b.order);
|
|
574
|
+
const radarEntries = collectItems(sortedDatasets, datasetVisibility).radar;
|
|
575
|
+
if (radarEntries.length === 0) {
|
|
576
|
+
this._fullReset();
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
this._entries = radarEntries;
|
|
580
|
+
const anyVisible = radarEntries.some((e) => e.visible);
|
|
581
|
+
if (!anyVisible) {
|
|
582
|
+
this._runAllHidden(features);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
const perAxisDomains = buildPerAxisDomains(radarEntries, yAxes);
|
|
586
|
+
const sharedCategoriesForDomain = sharedContext?.categories ?? Array.from(
|
|
587
|
+
new Set(
|
|
588
|
+
radarEntries.flatMap((ds) => {
|
|
589
|
+
const data = ds.props.data;
|
|
590
|
+
const cf = ds.props.categoryField;
|
|
591
|
+
if (!data || !cf) return [];
|
|
592
|
+
return data.map((item, i) => typeof cf === "function" ? cf(makeItemContext(item, i)) : item[cf]);
|
|
593
|
+
})
|
|
594
|
+
)
|
|
595
|
+
);
|
|
596
|
+
const isStacked = radarEntries.some((ds) => !!ds.props.stackId);
|
|
597
|
+
const perSpokeDomains = buildPerSpokeDomains(radarEntries, yAxes, sharedCategoriesForDomain, isStacked);
|
|
598
|
+
const referenceBoundaryValues = [];
|
|
599
|
+
for (const [key, feat] of features) {
|
|
600
|
+
if (typeof key === "string" && key.startsWith("referenceBand:")) {
|
|
601
|
+
const bp = feat.props;
|
|
602
|
+
if (bp.y1 != null) referenceBoundaryValues.push(bp.y1);
|
|
603
|
+
if (bp.y2 != null) referenceBoundaryValues.push(bp.y2);
|
|
604
|
+
} else if (typeof key === "string" && key.startsWith("referenceLine:")) {
|
|
605
|
+
const lp = feat.props;
|
|
606
|
+
if (lp.y != null) referenceBoundaryValues.push(lp.y);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
const defaultYAxis = yAxes ? Array.from(yAxes.values()).find((a) => !a.props.category) : void 0;
|
|
610
|
+
const yAxisProps = defaultYAxis?.props;
|
|
611
|
+
const baseLayout = calculateRadarLayout(radarEntries, chartArea, globalFont, sharedContext?.categories, sharedContext?.domain, perAxisDomains, referenceBoundaryValues, perSpokeDomains, yAxisProps?.tickCount);
|
|
612
|
+
if (yAxisProps) {
|
|
613
|
+
const g = baseLayout.grid;
|
|
614
|
+
if (yAxisProps.gridShape) g.shape = yAxisProps.gridShape;
|
|
615
|
+
if (yAxisProps.gridColor !== void 0) g.color = yAxisProps.gridColor;
|
|
616
|
+
if (yAxisProps.gridOpacity !== void 0) g.opacity = yAxisProps.gridOpacity;
|
|
617
|
+
if (yAxisProps.gridStrokeWidth !== void 0) g.width = yAxisProps.gridStrokeWidth;
|
|
618
|
+
if (yAxisProps.gridStyle !== void 0) g.style = yAxisProps.gridStyle;
|
|
619
|
+
}
|
|
620
|
+
const targetLayout = {
|
|
621
|
+
...baseLayout,
|
|
622
|
+
datasetIndex: 0
|
|
623
|
+
};
|
|
624
|
+
this._layout = targetLayout;
|
|
625
|
+
this._activeCenter = targetLayout.center;
|
|
626
|
+
const animConfig = features.get("animation")?.props;
|
|
627
|
+
const { enabled: animEnabled, duration, easing } = parseAnimationConfig(animConfig);
|
|
628
|
+
const fingerprint = buildRadarFingerprint(targetLayout, radarEntries);
|
|
629
|
+
const dataChanged = fingerprint !== this._lastFingerprint;
|
|
630
|
+
const shouldAnimate = animEnabled && duration > 0 && dataChanged;
|
|
631
|
+
if (!dataChanged) return;
|
|
632
|
+
if (this._animRafId !== null) {
|
|
633
|
+
cancelRaf(this._animRafId);
|
|
634
|
+
this._animRafId = null;
|
|
635
|
+
}
|
|
636
|
+
const sceneTargets = /* @__PURE__ */ new Map();
|
|
637
|
+
for (const sd of targetLayout.series) {
|
|
638
|
+
if (!sd.visible) continue;
|
|
639
|
+
const hasBase = !!sd.basePoints && sd.basePoints.length > 0;
|
|
640
|
+
for (let pi = 0; pi < sd.points.length; pi++) {
|
|
641
|
+
const p = sd.points[pi];
|
|
642
|
+
const base = hasBase ? sd.basePoints[pi] : null;
|
|
643
|
+
sceneTargets.set(pointKey(sd.id, p.categoryIndex), {
|
|
644
|
+
x: p.x,
|
|
645
|
+
y: p.y,
|
|
646
|
+
value: p.value,
|
|
647
|
+
baseX: base ? base.x : targetLayout.center.x,
|
|
648
|
+
baseY: base ? base.y : targetLayout.center.y,
|
|
649
|
+
baseValue: base ? base.value : 0,
|
|
650
|
+
seriesId: sd.id,
|
|
651
|
+
categoryIndex: p.categoryIndex,
|
|
652
|
+
angle: p.angle,
|
|
653
|
+
hasBase
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const opts = { numbers: { duration: shouldAnimate ? duration : 0, easing } };
|
|
658
|
+
this._scene.diff(sceneTargets, opts);
|
|
659
|
+
this._lastFingerprint = fingerprint;
|
|
660
|
+
const now = performance.now();
|
|
661
|
+
for (const sd of targetLayout.series) {
|
|
662
|
+
const hasBase = !!sd.basePoints && sd.basePoints.length > 0;
|
|
663
|
+
const settled = this._seriesSettledStyle.get(sd.id);
|
|
664
|
+
if (!hasBase) {
|
|
665
|
+
this._seriesFades.delete(sd.id);
|
|
666
|
+
this._seriesSettledStyle.set(sd.id, { fillOpacity: sd.fillOpacity, lineStrokeWidth: sd.lineStrokeWidth });
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
const targetFill = sd.visible ? sd.fillOpacity : 0;
|
|
670
|
+
const targetStroke = sd.visible ? sd.lineStrokeWidth : 0;
|
|
671
|
+
const settledFill = settled?.fillOpacity ?? 0;
|
|
672
|
+
const settledStroke = settled?.lineStrokeWidth ?? 0;
|
|
673
|
+
if (Math.abs(settledFill - targetFill) < 1e-3 && Math.abs(settledStroke - targetStroke) < 1e-3) {
|
|
674
|
+
this._seriesFades.delete(sd.id);
|
|
675
|
+
if (sd.visible) {
|
|
676
|
+
this._seriesSettledStyle.set(sd.id, { fillOpacity: sd.fillOpacity, lineStrokeWidth: sd.lineStrokeWidth });
|
|
677
|
+
}
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
if (!shouldAnimate) {
|
|
681
|
+
this._seriesFades.delete(sd.id);
|
|
682
|
+
this._seriesSettledStyle.set(sd.id, { fillOpacity: targetFill, lineStrokeWidth: targetStroke });
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
let fromFill = settledFill;
|
|
686
|
+
let fromStroke = settledStroke;
|
|
687
|
+
const existing = this._seriesFades.get(sd.id);
|
|
688
|
+
if (existing) {
|
|
689
|
+
const lerped = lerpSeriesFade(existing, now);
|
|
690
|
+
fromFill = lerped.fillOpacity;
|
|
691
|
+
fromStroke = lerped.lineStrokeWidth;
|
|
692
|
+
}
|
|
693
|
+
this._seriesFades.set(sd.id, {
|
|
694
|
+
fromFillOpacity: fromFill,
|
|
695
|
+
toFillOpacity: targetFill,
|
|
696
|
+
fromLineStrokeWidth: fromStroke,
|
|
697
|
+
toLineStrokeWidth: targetStroke,
|
|
698
|
+
startTime: -1,
|
|
699
|
+
duration,
|
|
700
|
+
easing
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
const liveSeriesIds = new Set(targetLayout.series.map((s) => s.id));
|
|
704
|
+
for (const id of [...this._seriesFades.keys()]) {
|
|
705
|
+
if (!liveSeriesIds.has(id)) this._seriesFades.delete(id);
|
|
706
|
+
}
|
|
707
|
+
this._updateGridLerp(targetLayout, shouldAnimate, duration, easing, yAxisProps?.tickCount);
|
|
708
|
+
if (shouldAnimate) {
|
|
709
|
+
this._renderSceneFrame();
|
|
710
|
+
this._startAnimLoop();
|
|
711
|
+
} else {
|
|
712
|
+
this._scene.tick(performance.now());
|
|
713
|
+
this._renderSceneFrame();
|
|
714
|
+
}
|
|
715
|
+
this._firstRender = false;
|
|
716
|
+
}
|
|
717
|
+
applyHover(hover) {
|
|
718
|
+
const hoverConfig = this.lastInput?.hoverConfig;
|
|
719
|
+
this.hoverState = { datasetId: hover.datasetId, index: hover.index, axisIndex: hover.axisIndex ?? null };
|
|
720
|
+
this.effectConfig = hoverConfig ? { hoverBrightness: hoverConfig.brightness ?? DEFAULT_HOVER_BRIGHTNESS, dimOpacity: hoverConfig.dimOpacity ?? DEFAULT_HOVER_DIM_OPACITY } : { hoverBrightness: 1, dimOpacity: 1 };
|
|
721
|
+
const layout = this.lastRenderedLayout ?? this._layout;
|
|
722
|
+
if (!layout || this._entries.length === 0 || !this.lastInput) return;
|
|
723
|
+
if (this.lastInput.renderer === "svg" && this.svgGroup) {
|
|
724
|
+
if (this._animRafId !== null) return;
|
|
725
|
+
reconcileSvgChildren(this.svgGroup, buildRadarSvgChildren(this, layout, this._entries, this.lastInput));
|
|
726
|
+
} else if (this.lastInput.renderer === "canvas") {
|
|
727
|
+
this.lastInput.requestRedraw?.();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
hitTest(x, y) {
|
|
731
|
+
if (!this._layout) return null;
|
|
732
|
+
return hitTestRadar(x, y, this._layout, this.lastInput?.theme ?? defaultLightTheme);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Shared-mode lookup: snap to the nearest spoke (categoryIndex) by angle and
|
|
736
|
+
* return every series' point at that spoke as `allSeries` (parity with
|
|
737
|
+
* cartesian bar/line shared tooltip).
|
|
738
|
+
*/
|
|
739
|
+
findAllNearest(x, y) {
|
|
740
|
+
const layout = this.lastRenderedLayout ?? this._layout;
|
|
741
|
+
if (!layout || layout.series.length === 0 || layout.categories.length === 0) return null;
|
|
742
|
+
const dx = x - layout.center.x;
|
|
743
|
+
const dy = y - layout.center.y;
|
|
744
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
745
|
+
if (dist > layout.radius * 1.15) return null;
|
|
746
|
+
let cursorAngle = Math.atan2(dx, -dy) * (180 / Math.PI);
|
|
747
|
+
if (cursorAngle < 0) cursorAngle += 360;
|
|
748
|
+
const angleStep = 360 / layout.categories.length;
|
|
749
|
+
const categoryIndex = Math.round(cursorAngle / angleStep) % layout.categories.length;
|
|
750
|
+
const label = layout.categories[categoryIndex] ?? "";
|
|
751
|
+
const allSeries = [];
|
|
752
|
+
let primary = null;
|
|
753
|
+
let bestDist = Infinity;
|
|
754
|
+
for (const sd of layout.series) {
|
|
755
|
+
if (!sd.visible) continue;
|
|
756
|
+
const pt = sd.points.find((p) => p.categoryIndex === categoryIndex);
|
|
757
|
+
if (!pt) continue;
|
|
758
|
+
allSeries.push({
|
|
759
|
+
datasetId: sd.id,
|
|
760
|
+
name: sd.name,
|
|
761
|
+
label,
|
|
762
|
+
color: sd.color ?? (sd.gradientColor ? getPrimaryColor(sd.gradientColor) : getDefaultColor(sd.seriesIdx, this.lastInput?.theme ?? defaultLightTheme)),
|
|
763
|
+
colorGradient: sd.gradientColor,
|
|
764
|
+
swatchColor: resolveSwatchColor({ color: sd.color ?? sd.gradientColor }, sd.seriesIdx, void 0, this.lastInput?.theme),
|
|
765
|
+
value: pt.value,
|
|
766
|
+
formattedValue: String(pt.value),
|
|
767
|
+
cursorFormattedValue: String(pt.value),
|
|
768
|
+
snapPixel: Math.sqrt((pt.x - layout.center.x) ** 2 + (pt.y - layout.center.y) ** 2)
|
|
769
|
+
});
|
|
770
|
+
const d = Math.sqrt((pt.x - x) ** 2 + (pt.y - y) ** 2);
|
|
771
|
+
if (d < bestDist) {
|
|
772
|
+
bestDist = d;
|
|
773
|
+
primary = {
|
|
774
|
+
datasetId: sd.id,
|
|
775
|
+
index: categoryIndex,
|
|
776
|
+
label,
|
|
777
|
+
value: pt.value,
|
|
778
|
+
color: sd.color ?? (sd.gradientColor ? getPrimaryColor(sd.gradientColor) : getDefaultColor(sd.seriesIdx, this.lastInput?.theme ?? defaultLightTheme)),
|
|
779
|
+
colorGradient: sd.gradientColor,
|
|
780
|
+
swatchColor: resolveSwatchColor({ color: sd.color ?? sd.gradientColor }, sd.seriesIdx, void 0, this.lastInput?.theme)
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (!primary) return null;
|
|
785
|
+
return { primary, allSeries };
|
|
786
|
+
}
|
|
787
|
+
renderCanvasContent(ctx) {
|
|
788
|
+
renderCanvasContent(this, ctx);
|
|
789
|
+
}
|
|
790
|
+
get hasData() {
|
|
791
|
+
return this._hasRadarDatasets;
|
|
792
|
+
}
|
|
793
|
+
get layout() {
|
|
794
|
+
return this.lastRenderedLayout ?? this._layout;
|
|
795
|
+
}
|
|
796
|
+
get markerData() {
|
|
797
|
+
return this._markerData;
|
|
798
|
+
}
|
|
799
|
+
destroy() {
|
|
800
|
+
if (this._animRafId !== null) {
|
|
801
|
+
cancelRaf(this._animRafId);
|
|
802
|
+
this._animRafId = null;
|
|
803
|
+
}
|
|
804
|
+
this._scene.reset();
|
|
805
|
+
this._seriesFades.clear();
|
|
806
|
+
this._seriesSettledStyle.clear();
|
|
807
|
+
this._gridLerp = null;
|
|
808
|
+
this._propertyOverrides.clear();
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Apply animated property values without triggering a full layout cycle.
|
|
812
|
+
* Called from the property-animation framework wrapper (RadialRenderer)
|
|
813
|
+
* each animation tick.
|
|
814
|
+
*
|
|
815
|
+
* Per-dataset: writes overrides into `_propertyOverrides` (or deletes the
|
|
816
|
+
* entry when the store has no live values for it), then triggers a frame
|
|
817
|
+
* rebuild so `_buildLayoutFromScene` re-merges into the rendered series
|
|
818
|
+
* and `renderToSvg` / `renderCanvasContent` see the merged props.
|
|
819
|
+
*
|
|
820
|
+
* SVG: re-renders imperatively via `_renderSceneFrame`. The wholesale
|
|
821
|
+
* DOM rebuild covers the `tension` path-rebuild concern — when tension
|
|
822
|
+
* changes, `buildSmoothPath` / `buildPointsPath` get called fresh by the
|
|
823
|
+
* next `renderToSvg` pass. Canvas: calls `requestRedraw` so the canvas
|
|
824
|
+
* pipeline repaints with the merged props baked in.
|
|
825
|
+
*/
|
|
826
|
+
applyPropertyAnimations(store) {
|
|
827
|
+
const layout = this._layout;
|
|
828
|
+
const input = this.lastInput;
|
|
829
|
+
if (!layout || !input) return;
|
|
830
|
+
let appliedAny = false;
|
|
831
|
+
for (const sd of layout.series) {
|
|
832
|
+
const overrides = resolveAnimatedProps(store, "radar", sd.id, RADAR_ANIMATABLE_PROPS);
|
|
833
|
+
if (Object.keys(overrides).length === 0) {
|
|
834
|
+
if (this._propertyOverrides.delete(sd.id)) appliedAny = true;
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
appliedAny = true;
|
|
838
|
+
this._propertyOverrides.set(sd.id, overrides);
|
|
839
|
+
}
|
|
840
|
+
if (!appliedAny) return;
|
|
841
|
+
this._renderSceneFrame();
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Full re-render of the current scene state.
|
|
845
|
+
*
|
|
846
|
+
* Used by the property-animation framework wrapper: when a property
|
|
847
|
+
* animation completes and its override is released from the store,
|
|
848
|
+
* `_renderSceneFrame()` rebuilds the series from `_propertyOverrides`-
|
|
849
|
+
* cleared base values so SVG attributes snap back to the layout-derived
|
|
850
|
+
* defaults.
|
|
851
|
+
*/
|
|
852
|
+
renderFrameCycle() {
|
|
853
|
+
this._renderSceneFrame();
|
|
854
|
+
}
|
|
855
|
+
// ================================================================
|
|
856
|
+
// PRIVATE — delegators to scene / paint sibling modules
|
|
857
|
+
// ================================================================
|
|
858
|
+
_fullReset() {
|
|
859
|
+
fullReset(this);
|
|
860
|
+
}
|
|
861
|
+
_runAllHidden(features) {
|
|
862
|
+
runAllHidden(this, features);
|
|
863
|
+
}
|
|
864
|
+
_updateGridLerp(targetLayout, shouldAnimate, duration, easing, tickCount) {
|
|
865
|
+
updateGridLerp(this, targetLayout, shouldAnimate, duration, easing, tickCount);
|
|
866
|
+
}
|
|
867
|
+
_currentGridDomain() {
|
|
868
|
+
return currentGridDomain(this);
|
|
869
|
+
}
|
|
870
|
+
_buildLayoutFromScene(now) {
|
|
871
|
+
return buildLayoutFromScene(this, now);
|
|
872
|
+
}
|
|
873
|
+
_renderSceneFrame() {
|
|
874
|
+
renderSceneFrame(this);
|
|
875
|
+
}
|
|
876
|
+
_startAnimLoop() {
|
|
877
|
+
startAnimLoop(this);
|
|
878
|
+
}
|
|
879
|
+
setMarkerData(data) {
|
|
880
|
+
setMarkerData(this, data);
|
|
881
|
+
}
|
|
882
|
+
buildRadarSvgChildren(layout, entries, input) {
|
|
883
|
+
return buildRadarSvgChildren(this, layout, entries, input);
|
|
884
|
+
}
|
|
885
|
+
renderToSvg(group, layout, entries, input) {
|
|
886
|
+
renderToSvg(this, group, layout, entries, input);
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
export { RadarRendererController };
|