@voila.dev/chart 5.0.114 → 5.0.117
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/canvas/paint-scene.d.ts.map +1 -1
- package/dist/canvas/paint-scene.js +3 -1
- package/dist/canvas/paint-scene.js.map +2 -2
- package/dist/contour/density.d.ts.map +1 -1
- package/dist/contour/density.js +2 -0
- package/dist/contour/density.js.map +2 -2
- package/dist/core/marks/area.d.ts.map +1 -1
- package/dist/core/marks/area.js +27 -11
- package/dist/core/marks/area.js.map +2 -2
- package/dist/core/marks/bar.d.ts.map +1 -1
- package/dist/core/marks/bar.js +2 -0
- package/dist/core/marks/bar.js.map +2 -2
- package/dist/core/marks/line.d.ts.map +1 -1
- package/dist/core/marks/line.js +13 -4
- package/dist/core/marks/line.js.map +2 -2
- package/dist/core/marks/polar.d.ts.map +1 -1
- package/dist/core/marks/polar.js +22 -5
- package/dist/core/marks/polar.js.map +2 -2
- package/dist/core/marks/shared.d.ts +8 -1
- package/dist/core/marks/shared.d.ts.map +1 -1
- package/dist/core/marks/shared.js.map +2 -2
- package/dist/core/marks/stats/difference.d.ts.map +1 -1
- package/dist/core/marks/stats/difference.js +20 -7
- package/dist/core/marks/stats/difference.js.map +2 -2
- package/dist/core/motion/arc-motion.d.ts +9 -0
- package/dist/core/motion/arc-motion.d.ts.map +1 -0
- package/dist/core/motion/arc-motion.js +67 -0
- package/dist/core/motion/arc-motion.js.map +7 -0
- package/dist/core/motion/enter-exit.d.ts +6 -0
- package/dist/core/motion/enter-exit.d.ts.map +1 -0
- package/dist/core/motion/enter-exit.js +20 -0
- package/dist/core/motion/enter-exit.js.map +7 -0
- package/dist/core/motion/leaving.d.ts +12 -0
- package/dist/core/motion/leaving.d.ts.map +1 -0
- package/dist/core/motion/leaving.js +33 -0
- package/dist/core/motion/leaving.js.map +7 -0
- package/dist/core/motion/motion-store.d.ts +4 -1
- package/dist/core/motion/motion-store.d.ts.map +1 -1
- package/dist/core/motion/motion-store.js +251 -100
- package/dist/core/motion/motion-store.js.map +3 -3
- package/dist/core/motion/points-motion.d.ts +6 -0
- package/dist/core/motion/points-motion.d.ts.map +1 -0
- package/dist/core/motion/points-motion.js +140 -0
- package/dist/core/motion/points-motion.js.map +7 -0
- package/dist/core/motion/strings.d.ts +18 -0
- package/dist/core/motion/strings.d.ts.map +1 -0
- package/dist/core/motion/strings.js +34 -0
- package/dist/core/motion/strings.js.map +7 -0
- package/dist/core/types.d.ts +85 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/geo/geo.d.ts.map +1 -1
- package/dist/geo/geo.js +2 -0
- package/dist/geo/geo.js.map +2 -2
- package/dist/react/chart.d.ts.map +1 -1
- package/dist/react/chart.js +6 -2
- package/dist/react/chart.js.map +2 -2
- package/dist/react/svg-scene.d.ts.map +1 -1
- package/dist/react/svg-scene.js +3 -1
- package/dist/react/svg-scene.js.map +2 -2
- package/dist/react/use-animated-scene.d.ts.map +1 -1
- package/dist/react/use-animated-scene.js +14 -2
- package/dist/react/use-animated-scene.js.map +2 -2
- package/dist/voronoi/voronoi.d.ts.map +1 -1
- package/dist/voronoi/voronoi.js +2 -0
- package/dist/voronoi/voronoi.js.map +2 -2
- package/package.json +2 -2
- package/src/canvas/paint-scene.ts +5 -1
- package/src/contour/density.ts +2 -0
- package/src/core/marks/area.ts +28 -13
- package/src/core/marks/bar.ts +2 -0
- package/src/core/marks/line.ts +15 -8
- package/src/core/marks/polar.ts +22 -5
- package/src/core/marks/shared.ts +8 -0
- package/src/core/marks/stats/difference.ts +28 -8
- package/src/core/motion/arc-motion.ts +113 -0
- package/src/core/motion/enter-exit.ts +44 -0
- package/src/core/motion/leaving.ts +55 -0
- package/src/core/motion/motion-store.ts +332 -109
- package/src/core/motion/points-motion.ts +190 -0
- package/src/core/motion/strings.ts +68 -0
- package/src/core/types.ts +98 -0
- package/src/geo/geo.ts +2 -0
- package/src/react/chart.tsx +8 -2
- package/src/react/svg-scene.tsx +5 -1
- package/src/react/use-animated-scene.ts +18 -2
- package/src/voronoi/voronoi.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paint-scene.d.ts","sourceRoot":"","sources":["../../src/canvas/paint-scene.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,UAAU,EAAa,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"paint-scene.d.ts","sourceRoot":"","sources":["../../src/canvas/paint-scene.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,UAAU,EAAa,MAAM,iBAAiB,CAAC;AA0LzE,6EAA6E;AAC7E,wBAAgB,UAAU,CACzB,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EAClC,UAAU,EAAE,MAAM,QAOlB"}
|
|
@@ -60,7 +60,9 @@ function fillAndStroke(environment, paint, draw) {
|
|
|
60
60
|
context.lineWidth = paint.strokeWidth ?? 1;
|
|
61
61
|
context.lineCap = paint.strokeLinecap ?? "butt";
|
|
62
62
|
context.lineJoin = paint.strokeLinejoin ?? "miter";
|
|
63
|
-
context.setLineDash(
|
|
63
|
+
context.setLineDash(
|
|
64
|
+
paint.drawn ? [paint.drawn.fraction * paint.drawn.length, paint.drawn.length] : dashes(paint.strokeDasharray)
|
|
65
|
+
);
|
|
64
66
|
draw("stroke");
|
|
65
67
|
context.setLineDash([]);
|
|
66
68
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/canvas/paint-scene.ts"],
|
|
4
|
-
"sourcesContent": ["import { roundedBarPath } from \"#/core/paths.ts\";\nimport type { ChartPaint, ChartScene, SceneNode } from \"#/core/types.ts\";\n\nconst CANVAS_BASELINE = {\n\ttop: \"top\",\n\tmiddle: \"middle\",\n\tbottom: \"bottom\",\n\talphabetic: \"alphabetic\",\n} as const satisfies Record<string, CanvasTextBaseline>;\n\nconst CANVAS_ALIGN = {\n\tstart: \"left\",\n\tmiddle: \"center\",\n\tend: \"right\",\n} as const satisfies Record<string, CanvasTextAlign>;\n\nconst HATCH_STEP = 6;\nconst hatchCache = new WeakMap<\n\tCanvasRenderingContext2D,\n\tMap<string, CanvasPattern | string>\n>();\n\n/** Diagonal lines every few pixels in the colour, as the SVG pattern draws them. */\nfunction hatchPattern(\n\tcontext: CanvasRenderingContext2D,\n\tcolor: string,\n): CanvasPattern | string {\n\tconst cache =\n\t\thatchCache.get(context) ?? new Map<string, CanvasPattern | string>();\n\thatchCache.set(context, cache);\n\tconst cached = cache.get(color);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\tconst tile = document.createElement(\"canvas\");\n\ttile.width = HATCH_STEP;\n\ttile.height = HATCH_STEP;\n\tconst pen = tile.getContext(\"2d\");\n\tif (pen === null) {\n\t\treturn color;\n\t}\n\tpen.strokeStyle = color;\n\tpen.lineWidth = 1.5;\n\tpen.beginPath();\n\t// One diagonal across the tile, plus the two corner stubs that join it to\n\t// the neighbouring tiles' lines.\n\tpen.moveTo(0, HATCH_STEP);\n\tpen.lineTo(HATCH_STEP, 0);\n\tpen.moveTo(-1, 1);\n\tpen.lineTo(1, -1);\n\tpen.moveTo(HATCH_STEP - 1, HATCH_STEP + 1);\n\tpen.lineTo(HATCH_STEP + 1, HATCH_STEP - 1);\n\tpen.stroke();\n\tconst pattern = context.createPattern(tile, \"repeat\") ?? color;\n\tcache.set(color, pattern);\n\treturn pattern;\n}\n\nfunction dashes(dasharray: string | undefined): number[] {\n\tif (!dasharray) {\n\t\treturn [];\n\t}\n\treturn dasharray\n\t\t.split(/[\\s,]+/)\n\t\t.map(Number)\n\t\t.filter((value) => Number.isFinite(value));\n}\n\ninterface PaintEnvironment {\n\treadonly context: CanvasRenderingContext2D;\n\treadonly resolve: (color: string) => string;\n\treadonly fontFamily: string;\n}\n\nfunction fillAndStroke(\n\tenvironment: PaintEnvironment,\n\tpaint: ChartPaint,\n\tdraw: (mode: \"fill\" | \"stroke\") => void,\n) {\n\tconst { context, resolve } = environment;\n\tconst opacity = paint.opacity ?? 1;\n\tif (paint.fill && paint.fill !== \"none\") {\n\t\tcontext.globalAlpha = opacity * (paint.fillOpacity ?? 1);\n\t\tcontext.fillStyle = paint.hatch\n\t\t\t? hatchPattern(context, resolve(paint.fill))\n\t\t\t: resolve(paint.fill);\n\t\tdraw(\"fill\");\n\t}\n\tif (paint.stroke && paint.stroke !== \"none\") {\n\t\tcontext.globalAlpha = opacity * (paint.strokeOpacity ?? 1);\n\t\tcontext.strokeStyle = resolve(paint.stroke);\n\t\tcontext.lineWidth = paint.strokeWidth ?? 1;\n\t\tcontext.lineCap = paint.strokeLinecap ?? \"butt\";\n\t\tcontext.lineJoin = paint.strokeLinejoin ?? \"miter\";\n\t\tcontext.setLineDash(dashes(paint.strokeDasharray));\n\t\tdraw(\"stroke\");\n\t\tcontext.setLineDash([]);\n\t}\n\tcontext.globalAlpha = 1;\n}\n\nfunction paintNode(environment: PaintEnvironment, node: SceneNode) {\n\tconst { context } = environment;\n\tswitch (node.kind) {\n\t\tcase \"group\":\n\t\t\tcontext.save();\n\t\t\tif (node.translate) {\n\t\t\t\tcontext.translate(node.translate.x, node.translate.y);\n\t\t\t}\n\t\t\tif (node.clip) {\n\t\t\t\tcontext.beginPath();\n\t\t\t\tcontext.rect(\n\t\t\t\t\tnode.clip.x,\n\t\t\t\t\tnode.clip.y,\n\t\t\t\t\tnode.clip.width,\n\t\t\t\t\tnode.clip.height,\n\t\t\t\t);\n\t\t\t\tcontext.clip();\n\t\t\t}\n\t\t\tfor (const child of node.children) {\n\t\t\t\tpaintNode(environment, child);\n\t\t\t}\n\t\t\tcontext.restore();\n\t\t\treturn;\n\t\tcase \"rect\": {\n\t\t\tconst path = node.corners\n\t\t\t\t? new Path2D(roundedBarPath({ ...node, radius: node.corners }))\n\t\t\t\t: undefined;\n\t\t\tfillAndStroke(environment, node.paint, (mode) => {\n\t\t\t\tif (path) {\n\t\t\t\t\tcontext[mode](path);\n\t\t\t\t} else if (mode === \"fill\") {\n\t\t\t\t\tcontext.fillRect(node.x, node.y, node.width, node.height);\n\t\t\t\t} else {\n\t\t\t\t\tcontext.strokeRect(node.x, node.y, node.width, node.height);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tcase \"path\": {\n\t\t\tif (node.d === \"\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst path = new Path2D(node.d);\n\t\t\tfillAndStroke(environment, node.paint, (mode) => context[mode](path));\n\t\t\treturn;\n\t\t}\n\t\tcase \"circle\": {\n\t\t\tconst path = new Path2D();\n\t\t\tpath.arc(node.cx, node.cy, node.r, 0, Math.PI * 2);\n\t\t\tfillAndStroke(environment, node.paint, (mode) => context[mode](path));\n\t\t\treturn;\n\t\t}\n\t\tcase \"line\": {\n\t\t\tconst path = new Path2D();\n\t\t\tpath.moveTo(node.x1, node.y1);\n\t\t\tpath.lineTo(node.x2, node.y2);\n\t\t\tfillAndStroke(environment, { ...node.paint, fill: undefined }, () =>\n\t\t\t\tcontext.stroke(path),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tcase \"text\": {\n\t\t\tconst { paint } = node;\n\t\t\tcontext.save();\n\t\t\tcontext.translate(node.x, node.y);\n\t\t\tif (node.rotate) {\n\t\t\t\tcontext.rotate((node.rotate * Math.PI) / 180);\n\t\t\t}\n\t\t\tcontext.font = `${paint.fontWeight ?? 400} ${paint.fontSize ?? 12}px ${environment.fontFamily}`;\n\t\t\tcontext.textAlign = CANVAS_ALIGN[paint.textAnchor ?? \"start\"];\n\t\t\tcontext.textBaseline = CANVAS_BASELINE[paint.baseline ?? \"alphabetic\"];\n\t\t\tfillAndStroke(environment, paint, (mode) =>\n\t\t\t\tmode === \"fill\"\n\t\t\t\t\t? context.fillText(node.text, 0, 0)\n\t\t\t\t\t: context.strokeText(node.text, 0, 0),\n\t\t\t);\n\t\t\tcontext.restore();\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/** Paints the whole scene. The canvas is already scaled to device pixels. */\nexport function paintScene(\n\tcontext: CanvasRenderingContext2D,\n\tscene: ChartScene,\n\tresolve: (color: string) => string,\n\tfontFamily: string,\n) {\n\tcontext.clearRect(0, 0, scene.width, scene.height);\n\tconst environment = { context, resolve, fontFamily };\n\tfor (const node of scene.nodes) {\n\t\tpaintNode(environment, node);\n\t}\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAG/B,MAAM,kBAAkB;AAAA,EACvB,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,YAAY;AACb;AAEA,MAAM,eAAe;AAAA,EACpB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AACN;AAEA,MAAM,aAAa;AACnB,MAAM,aAAa,oBAAI,QAGrB;AAGF,SAAS,aACR,SACA,OACyB;AACzB,QAAM,QACL,WAAW,IAAI,OAAO,KAAK,oBAAI,IAAoC;AACpE,aAAW,IAAI,SAAS,KAAK;AAC7B,QAAM,SAAS,MAAM,IAAI,KAAK;AAC9B,MAAI,WAAW,QAAW;AACzB,WAAO;AAAA,EACR;AACA,QAAM,OAAO,SAAS,cAAc,QAAQ;AAC5C,OAAK,QAAQ;AACb,OAAK,SAAS;AACd,QAAM,MAAM,KAAK,WAAW,IAAI;AAChC,MAAI,QAAQ,MAAM;AACjB,WAAO;AAAA,EACR;AACA,MAAI,cAAc;AAClB,MAAI,YAAY;AAChB,MAAI,UAAU;AAGd,MAAI,OAAO,GAAG,UAAU;AACxB,MAAI,OAAO,YAAY,CAAC;AACxB,MAAI,OAAO,IAAI,CAAC;AAChB,MAAI,OAAO,GAAG,EAAE;AAChB,MAAI,OAAO,aAAa,GAAG,aAAa,CAAC;AACzC,MAAI,OAAO,aAAa,GAAG,aAAa,CAAC;AACzC,MAAI,OAAO;AACX,QAAM,UAAU,QAAQ,cAAc,MAAM,QAAQ,KAAK;AACzD,QAAM,IAAI,OAAO,OAAO;AACxB,SAAO;AACR;AAEA,SAAS,OAAO,WAAyC;AACxD,MAAI,CAAC,WAAW;AACf,WAAO,CAAC;AAAA,EACT;AACA,SAAO,UACL,MAAM,QAAQ,EACd,IAAI,MAAM,EACV,OAAO,CAAC,UAAU,OAAO,SAAS,KAAK,CAAC;AAC3C;AAQA,SAAS,cACR,aACA,OACA,MACC;AACD,QAAM,EAAE,SAAS,QAAQ,IAAI;AAC7B,QAAM,UAAU,MAAM,WAAW;AACjC,MAAI,MAAM,QAAQ,MAAM,SAAS,QAAQ;AACxC,YAAQ,cAAc,WAAW,MAAM,eAAe;AACtD,YAAQ,YAAY,MAAM,QACvB,aAAa,SAAS,QAAQ,MAAM,IAAI,CAAC,IACzC,QAAQ,MAAM,IAAI;AACrB,SAAK,MAAM;AAAA,EACZ;AACA,MAAI,MAAM,UAAU,MAAM,WAAW,QAAQ;AAC5C,YAAQ,cAAc,WAAW,MAAM,iBAAiB;AACxD,YAAQ,cAAc,QAAQ,MAAM,MAAM;AAC1C,YAAQ,YAAY,MAAM,eAAe;AACzC,YAAQ,UAAU,MAAM,iBAAiB;AACzC,YAAQ,WAAW,MAAM,kBAAkB;AAC3C,YAAQ,
|
|
4
|
+
"sourcesContent": ["import { roundedBarPath } from \"#/core/paths.ts\";\nimport type { ChartPaint, ChartScene, SceneNode } from \"#/core/types.ts\";\n\nconst CANVAS_BASELINE = {\n\ttop: \"top\",\n\tmiddle: \"middle\",\n\tbottom: \"bottom\",\n\talphabetic: \"alphabetic\",\n} as const satisfies Record<string, CanvasTextBaseline>;\n\nconst CANVAS_ALIGN = {\n\tstart: \"left\",\n\tmiddle: \"center\",\n\tend: \"right\",\n} as const satisfies Record<string, CanvasTextAlign>;\n\nconst HATCH_STEP = 6;\nconst hatchCache = new WeakMap<\n\tCanvasRenderingContext2D,\n\tMap<string, CanvasPattern | string>\n>();\n\n/** Diagonal lines every few pixels in the colour, as the SVG pattern draws them. */\nfunction hatchPattern(\n\tcontext: CanvasRenderingContext2D,\n\tcolor: string,\n): CanvasPattern | string {\n\tconst cache =\n\t\thatchCache.get(context) ?? new Map<string, CanvasPattern | string>();\n\thatchCache.set(context, cache);\n\tconst cached = cache.get(color);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\tconst tile = document.createElement(\"canvas\");\n\ttile.width = HATCH_STEP;\n\ttile.height = HATCH_STEP;\n\tconst pen = tile.getContext(\"2d\");\n\tif (pen === null) {\n\t\treturn color;\n\t}\n\tpen.strokeStyle = color;\n\tpen.lineWidth = 1.5;\n\tpen.beginPath();\n\t// One diagonal across the tile, plus the two corner stubs that join it to\n\t// the neighbouring tiles' lines.\n\tpen.moveTo(0, HATCH_STEP);\n\tpen.lineTo(HATCH_STEP, 0);\n\tpen.moveTo(-1, 1);\n\tpen.lineTo(1, -1);\n\tpen.moveTo(HATCH_STEP - 1, HATCH_STEP + 1);\n\tpen.lineTo(HATCH_STEP + 1, HATCH_STEP - 1);\n\tpen.stroke();\n\tconst pattern = context.createPattern(tile, \"repeat\") ?? color;\n\tcache.set(color, pattern);\n\treturn pattern;\n}\n\nfunction dashes(dasharray: string | undefined): number[] {\n\tif (!dasharray) {\n\t\treturn [];\n\t}\n\treturn dasharray\n\t\t.split(/[\\s,]+/)\n\t\t.map(Number)\n\t\t.filter((value) => Number.isFinite(value));\n}\n\ninterface PaintEnvironment {\n\treadonly context: CanvasRenderingContext2D;\n\treadonly resolve: (color: string) => string;\n\treadonly fontFamily: string;\n}\n\nfunction fillAndStroke(\n\tenvironment: PaintEnvironment,\n\tpaint: ChartPaint,\n\tdraw: (mode: \"fill\" | \"stroke\") => void,\n) {\n\tconst { context, resolve } = environment;\n\tconst opacity = paint.opacity ?? 1;\n\tif (paint.fill && paint.fill !== \"none\") {\n\t\tcontext.globalAlpha = opacity * (paint.fillOpacity ?? 1);\n\t\tcontext.fillStyle = paint.hatch\n\t\t\t? hatchPattern(context, resolve(paint.fill))\n\t\t\t: resolve(paint.fill);\n\t\tdraw(\"fill\");\n\t}\n\tif (paint.stroke && paint.stroke !== \"none\") {\n\t\tcontext.globalAlpha = opacity * (paint.strokeOpacity ?? 1);\n\t\tcontext.strokeStyle = resolve(paint.stroke);\n\t\tcontext.lineWidth = paint.strokeWidth ?? 1;\n\t\tcontext.lineCap = paint.strokeLinecap ?? \"butt\";\n\t\tcontext.lineJoin = paint.strokeLinejoin ?? \"miter\";\n\t\tcontext.setLineDash(\n\t\t\tpaint.drawn\n\t\t\t\t? [paint.drawn.fraction * paint.drawn.length, paint.drawn.length]\n\t\t\t\t: dashes(paint.strokeDasharray),\n\t\t);\n\t\tdraw(\"stroke\");\n\t\tcontext.setLineDash([]);\n\t}\n\tcontext.globalAlpha = 1;\n}\n\nfunction paintNode(environment: PaintEnvironment, node: SceneNode) {\n\tconst { context } = environment;\n\tswitch (node.kind) {\n\t\tcase \"group\":\n\t\t\tcontext.save();\n\t\t\tif (node.translate) {\n\t\t\t\tcontext.translate(node.translate.x, node.translate.y);\n\t\t\t}\n\t\t\tif (node.clip) {\n\t\t\t\tcontext.beginPath();\n\t\t\t\tcontext.rect(\n\t\t\t\t\tnode.clip.x,\n\t\t\t\t\tnode.clip.y,\n\t\t\t\t\tnode.clip.width,\n\t\t\t\t\tnode.clip.height,\n\t\t\t\t);\n\t\t\t\tcontext.clip();\n\t\t\t}\n\t\t\tfor (const child of node.children) {\n\t\t\t\tpaintNode(environment, child);\n\t\t\t}\n\t\t\tcontext.restore();\n\t\t\treturn;\n\t\tcase \"rect\": {\n\t\t\tconst path = node.corners\n\t\t\t\t? new Path2D(roundedBarPath({ ...node, radius: node.corners }))\n\t\t\t\t: undefined;\n\t\t\tfillAndStroke(environment, node.paint, (mode) => {\n\t\t\t\tif (path) {\n\t\t\t\t\tcontext[mode](path);\n\t\t\t\t} else if (mode === \"fill\") {\n\t\t\t\t\tcontext.fillRect(node.x, node.y, node.width, node.height);\n\t\t\t\t} else {\n\t\t\t\t\tcontext.strokeRect(node.x, node.y, node.width, node.height);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tcase \"path\": {\n\t\t\tif (node.d === \"\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst path = new Path2D(node.d);\n\t\t\tfillAndStroke(environment, node.paint, (mode) => context[mode](path));\n\t\t\treturn;\n\t\t}\n\t\tcase \"circle\": {\n\t\t\tconst path = new Path2D();\n\t\t\tpath.arc(node.cx, node.cy, node.r, 0, Math.PI * 2);\n\t\t\tfillAndStroke(environment, node.paint, (mode) => context[mode](path));\n\t\t\treturn;\n\t\t}\n\t\tcase \"line\": {\n\t\t\tconst path = new Path2D();\n\t\t\tpath.moveTo(node.x1, node.y1);\n\t\t\tpath.lineTo(node.x2, node.y2);\n\t\t\tfillAndStroke(environment, { ...node.paint, fill: undefined }, () =>\n\t\t\t\tcontext.stroke(path),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tcase \"text\": {\n\t\t\tconst { paint } = node;\n\t\t\tcontext.save();\n\t\t\tcontext.translate(node.x, node.y);\n\t\t\tif (node.rotate) {\n\t\t\t\tcontext.rotate((node.rotate * Math.PI) / 180);\n\t\t\t}\n\t\t\tcontext.font = `${paint.fontWeight ?? 400} ${paint.fontSize ?? 12}px ${environment.fontFamily}`;\n\t\t\tcontext.textAlign = CANVAS_ALIGN[paint.textAnchor ?? \"start\"];\n\t\t\tcontext.textBaseline = CANVAS_BASELINE[paint.baseline ?? \"alphabetic\"];\n\t\t\tfillAndStroke(environment, paint, (mode) =>\n\t\t\t\tmode === \"fill\"\n\t\t\t\t\t? context.fillText(node.text, 0, 0)\n\t\t\t\t\t: context.strokeText(node.text, 0, 0),\n\t\t\t);\n\t\t\tcontext.restore();\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/** Paints the whole scene. The canvas is already scaled to device pixels. */\nexport function paintScene(\n\tcontext: CanvasRenderingContext2D,\n\tscene: ChartScene,\n\tresolve: (color: string) => string,\n\tfontFamily: string,\n) {\n\tcontext.clearRect(0, 0, scene.width, scene.height);\n\tconst environment = { context, resolve, fontFamily };\n\tfor (const node of scene.nodes) {\n\t\tpaintNode(environment, node);\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"density.d.ts","sourceRoot":"","sources":["../../src/contour/density.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"density.d.ts","sourceRoot":"","sources":["../../src/contour/density.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACX,aAAa,EACb,SAAS,EACT,UAAU,EAEV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,gBAAgB,CAAC,MAAM;IACvC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9C,QAAQ,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9C,4BAA4B;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,uCAAuC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAC/B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAC/B,SAAS,CA0DX"}
|
package/dist/contour/density.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mixPath } from "@voila.dev/motion";
|
|
1
2
|
import { contourDensity } from "d3-contour";
|
|
2
3
|
import { isPlaceable, readChannel } from "../core/channel.js";
|
|
3
4
|
import { markId, valueOn } from "../core/marks/shared.js";
|
|
@@ -39,6 +40,7 @@ function density2d(data, options) {
|
|
|
39
40
|
key: `${id}:${index}`,
|
|
40
41
|
role: "mark",
|
|
41
42
|
d: multiPolygonPath(level.coordinates, plot.x, plot.y),
|
|
43
|
+
morph: mixPath,
|
|
42
44
|
paint: options.stroke ? {
|
|
43
45
|
fill: "none",
|
|
44
46
|
stroke: color,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/contour/density.ts"],
|
|
4
|
-
"sourcesContent": ["import { contourDensity } from \"d3-contour\";\nimport { isPlaceable, readChannel } from \"#/core/channel.ts\";\nimport { markId, valueOn } from \"#/core/marks/shared.ts\";\nimport { multiPolygonPath } from \"#/core/paths.ts\";\nimport type {\n\tChartAccessor,\n\tChartMark,\n\tChartValue,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface Density2dOptions<TDatum> {\n\treadonly id?: string;\n\treadonly x: ChartAccessor<TDatum, ChartValue>;\n\treadonly y: ChartAccessor<TDatum, ChartValue>;\n\t/** Smoothing, in pixels. */\n\treadonly bandwidth?: number;\n\t/** How many density levels to draw. */\n\treadonly thresholds?: number;\n\treadonly fill?: string;\n\t/** Outline the levels instead of filling them. */\n\treadonly stroke?: boolean;\n}\n\n/**\n * Where points crowd, as nested contours: the shape of a scatter too dense\n * to read. Decorative on its own (the levels are not values a reader can\n * visit), so draw the points too, or give the chart a description.\n */\nexport function density2d<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: Density2dOptions<TDatum>,\n): ChartMark {\n\tconst xs = readChannel(data, options.x);\n\tconst ys = readChannel(data, options.y);\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tchannels: {\n\t\t\tx: { values: xs.filter(isPlaceable) },\n\t\t\ty: { values: ys.filter(isPlaceable) },\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, \"density2d\", context);\n\t\t\tconst { x: xScale, y: yScale } = context.scales;\n\t\t\tif (xScale === undefined || yScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst { plot } = context;\n\t\t\tconst pixels: Array<[number, number]> = [];\n\t\t\tfor (const [index, raw] of xs.entries()) {\n\t\t\t\tconst x = valueOn(xScale, raw);\n\t\t\t\tconst y = valueOn(yScale, ys[index]);\n\t\t\t\tif (x !== undefined && y !== undefined) {\n\t\t\t\t\tpixels.push([xScale.center(x) - plot.x, yScale.center(y) - plot.y]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst levels = contourDensity()\n\t\t\t\t.x((pixel) => pixel[0])\n\t\t\t\t.y((pixel) => pixel[1])\n\t\t\t\t.size([\n\t\t\t\t\tMath.max(1, Math.round(plot.width)),\n\t\t\t\t\tMath.max(1, Math.round(plot.height)),\n\t\t\t\t])\n\t\t\t\t.bandwidth(options.bandwidth ?? 20)\n\t\t\t\t.thresholds(options.thresholds ?? 8)(pixels);\n\t\t\tconst color = options.fill ?? context.paletteColor(context.markIndex);\n\t\t\tconst nodes: SceneNode[] = levels.map((level, index) => {\n\t\t\t\tconst share = levels.length <= 1 ? 1 : (index + 1) / levels.length;\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: `${id}:${index}`,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\td: multiPolygonPath(level.coordinates as never, plot.x, plot.y),\n\t\t\t\t\tpaint: options.stroke\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfill: \"none\",\n\t\t\t\t\t\t\t\tstroke: color,\n\t\t\t\t\t\t\t\tstrokeWidth: 1,\n\t\t\t\t\t\t\t\tstrokeOpacity: 0.3 + 0.7 * share,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: { fill: color, fillOpacity: 0.12 },\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tnodes: nodes.filter((node) => node.kind !== \"path\" || node.d !== \"\"),\n\t\t\t};\n\t\t},\n\t};\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAsB;AAC/B,SAAS,aAAa,mBAAmB;AACzC,SAAS,QAAQ,eAAe;AAChC,SAAS,wBAAwB;AA0B1B,SAAS,UACf,MACA,SACY;AACZ,QAAM,KAAK,YAAY,MAAM,QAAQ,CAAC;AACtC,QAAM,KAAK,YAAY,MAAM,QAAQ,CAAC;AACtC,SAAO;AAAA,IACN,IAAI,QAAQ;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,MACT,GAAG,EAAE,QAAQ,GAAG,OAAO,WAAW,EAAE;AAAA,MACpC,GAAG,EAAE,QAAQ,GAAG,OAAO,WAAW,EAAE;AAAA,IACrC;AAAA,IACA,OAAO,SAAS;AACf,YAAM,KAAK,OAAO,QAAQ,IAAI,aAAa,OAAO;AAClD,YAAM,EAAE,GAAG,QAAQ,GAAG,OAAO,IAAI,QAAQ;AACzC,UAAI,WAAW,UAAa,WAAW,QAAW;AACjD,eAAO,EAAE,OAAO,CAAC,EAAE;AAAA,MACpB;AACA,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,SAAkC,CAAC;AACzC,iBAAW,CAAC,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG;AACxC,cAAM,IAAI,QAAQ,QAAQ,GAAG;AAC7B,cAAM,IAAI,QAAQ,QAAQ,GAAG,KAAK,CAAC;AACnC,YAAI,MAAM,UAAa,MAAM,QAAW;AACvC,iBAAO,KAAK,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;AAAA,QACnE;AAAA,MACD;AACA,YAAM,SAAS,eAAe,EAC5B,EAAE,CAAC,UAAU,MAAM,CAAC,CAAC,EACrB,EAAE,CAAC,UAAU,MAAM,CAAC,CAAC,EACrB,KAAK;AAAA,QACL,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,QAClC,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,MAAM,CAAC;AAAA,MACpC,CAAC,EACA,UAAU,QAAQ,aAAa,EAAE,EACjC,WAAW,QAAQ,cAAc,CAAC,EAAE,MAAM;AAC5C,YAAM,QAAQ,QAAQ,QAAQ,QAAQ,aAAa,QAAQ,SAAS;AACpE,YAAM,QAAqB,OAAO,IAAI,CAAC,OAAO,UAAU;AACvD,cAAM,QAAQ,OAAO,UAAU,IAAI,KAAK,QAAQ,KAAK,OAAO;AAC5D,eAAO;AAAA,UACN,MAAM;AAAA,UACN,KAAK,GAAG,EAAE,IAAI,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,GAAG,iBAAiB,MAAM,aAAsB,KAAK,GAAG,KAAK,CAAC;AAAA,UAC9D,OAAO,QAAQ,SACZ;AAAA,YACA,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,eAAe,MAAM,MAAM;AAAA,UAC5B,IACC,EAAE,MAAM,OAAO,aAAa,KAAK;AAAA,QACrC;AAAA,MACD,CAAC;AACD,aAAO;AAAA,QACN,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,UAAU,KAAK,MAAM,EAAE;AAAA,MACpE;AAAA,IACD;AAAA,EACD;AACD;",
|
|
4
|
+
"sourcesContent": ["import { mixPath } from \"@voila.dev/motion\";\nimport { contourDensity } from \"d3-contour\";\nimport { isPlaceable, readChannel } from \"#/core/channel.ts\";\nimport { markId, valueOn } from \"#/core/marks/shared.ts\";\nimport { multiPolygonPath } from \"#/core/paths.ts\";\nimport type {\n\tChartAccessor,\n\tChartMark,\n\tChartValue,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface Density2dOptions<TDatum> {\n\treadonly id?: string;\n\treadonly x: ChartAccessor<TDatum, ChartValue>;\n\treadonly y: ChartAccessor<TDatum, ChartValue>;\n\t/** Smoothing, in pixels. */\n\treadonly bandwidth?: number;\n\t/** How many density levels to draw. */\n\treadonly thresholds?: number;\n\treadonly fill?: string;\n\t/** Outline the levels instead of filling them. */\n\treadonly stroke?: boolean;\n}\n\n/**\n * Where points crowd, as nested contours: the shape of a scatter too dense\n * to read. Decorative on its own (the levels are not values a reader can\n * visit), so draw the points too, or give the chart a description.\n */\nexport function density2d<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: Density2dOptions<TDatum>,\n): ChartMark {\n\tconst xs = readChannel(data, options.x);\n\tconst ys = readChannel(data, options.y);\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tchannels: {\n\t\t\tx: { values: xs.filter(isPlaceable) },\n\t\t\ty: { values: ys.filter(isPlaceable) },\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, \"density2d\", context);\n\t\t\tconst { x: xScale, y: yScale } = context.scales;\n\t\t\tif (xScale === undefined || yScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst { plot } = context;\n\t\t\tconst pixels: Array<[number, number]> = [];\n\t\t\tfor (const [index, raw] of xs.entries()) {\n\t\t\t\tconst x = valueOn(xScale, raw);\n\t\t\t\tconst y = valueOn(yScale, ys[index]);\n\t\t\t\tif (x !== undefined && y !== undefined) {\n\t\t\t\t\tpixels.push([xScale.center(x) - plot.x, yScale.center(y) - plot.y]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst levels = contourDensity()\n\t\t\t\t.x((pixel) => pixel[0])\n\t\t\t\t.y((pixel) => pixel[1])\n\t\t\t\t.size([\n\t\t\t\t\tMath.max(1, Math.round(plot.width)),\n\t\t\t\t\tMath.max(1, Math.round(plot.height)),\n\t\t\t\t])\n\t\t\t\t.bandwidth(options.bandwidth ?? 20)\n\t\t\t\t.thresholds(options.thresholds ?? 8)(pixels);\n\t\t\tconst color = options.fill ?? context.paletteColor(context.markIndex);\n\t\t\tconst nodes: SceneNode[] = levels.map((level, index) => {\n\t\t\t\tconst share = levels.length <= 1 ? 1 : (index + 1) / levels.length;\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: `${id}:${index}`,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\td: multiPolygonPath(level.coordinates as never, plot.x, plot.y),\n\t\t\t\t\tmorph: mixPath,\n\t\t\t\t\tpaint: options.stroke\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tfill: \"none\",\n\t\t\t\t\t\t\t\tstroke: color,\n\t\t\t\t\t\t\t\tstrokeWidth: 1,\n\t\t\t\t\t\t\t\tstrokeOpacity: 0.3 + 0.7 * share,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: { fill: color, fillOpacity: 0.12 },\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tnodes: nodes.filter((node) => node.kind !== \"path\" || node.d !== \"\"),\n\t\t\t};\n\t\t},\n\t};\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,aAAa,mBAAmB;AACzC,SAAS,QAAQ,eAAe;AAChC,SAAS,wBAAwB;AA0B1B,SAAS,UACf,MACA,SACY;AACZ,QAAM,KAAK,YAAY,MAAM,QAAQ,CAAC;AACtC,QAAM,KAAK,YAAY,MAAM,QAAQ,CAAC;AACtC,SAAO;AAAA,IACN,IAAI,QAAQ;AAAA,IACZ,YAAY;AAAA,IACZ,UAAU;AAAA,MACT,GAAG,EAAE,QAAQ,GAAG,OAAO,WAAW,EAAE;AAAA,MACpC,GAAG,EAAE,QAAQ,GAAG,OAAO,WAAW,EAAE;AAAA,IACrC;AAAA,IACA,OAAO,SAAS;AACf,YAAM,KAAK,OAAO,QAAQ,IAAI,aAAa,OAAO;AAClD,YAAM,EAAE,GAAG,QAAQ,GAAG,OAAO,IAAI,QAAQ;AACzC,UAAI,WAAW,UAAa,WAAW,QAAW;AACjD,eAAO,EAAE,OAAO,CAAC,EAAE;AAAA,MACpB;AACA,YAAM,EAAE,KAAK,IAAI;AACjB,YAAM,SAAkC,CAAC;AACzC,iBAAW,CAAC,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG;AACxC,cAAM,IAAI,QAAQ,QAAQ,GAAG;AAC7B,cAAM,IAAI,QAAQ,QAAQ,GAAG,KAAK,CAAC;AACnC,YAAI,MAAM,UAAa,MAAM,QAAW;AACvC,iBAAO,KAAK,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;AAAA,QACnE;AAAA,MACD;AACA,YAAM,SAAS,eAAe,EAC5B,EAAE,CAAC,UAAU,MAAM,CAAC,CAAC,EACrB,EAAE,CAAC,UAAU,MAAM,CAAC,CAAC,EACrB,KAAK;AAAA,QACL,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,QAClC,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,MAAM,CAAC;AAAA,MACpC,CAAC,EACA,UAAU,QAAQ,aAAa,EAAE,EACjC,WAAW,QAAQ,cAAc,CAAC,EAAE,MAAM;AAC5C,YAAM,QAAQ,QAAQ,QAAQ,QAAQ,aAAa,QAAQ,SAAS;AACpE,YAAM,QAAqB,OAAO,IAAI,CAAC,OAAO,UAAU;AACvD,cAAM,QAAQ,OAAO,UAAU,IAAI,KAAK,QAAQ,KAAK,OAAO;AAC5D,eAAO;AAAA,UACN,MAAM;AAAA,UACN,KAAK,GAAG,EAAE,IAAI,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,GAAG,iBAAiB,MAAM,aAAsB,KAAK,GAAG,KAAK,CAAC;AAAA,UAC9D,OAAO;AAAA,UACP,OAAO,QAAQ,SACZ;AAAA,YACA,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,eAAe,MAAM,MAAM;AAAA,UAC5B,IACC,EAAE,MAAM,OAAO,aAAa,KAAK;AAAA,QACrC;AAAA,MACD,CAAC;AACD,aAAO;AAAA,QACN,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,UAAU,KAAK,MAAM,EAAE;AAAA,MACpE;AAAA,IACD;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area.d.ts","sourceRoot":"","sources":["../../../src/core/marks/area.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,gBAAgB,EAOrB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"area.d.ts","sourceRoot":"","sources":["../../../src/core/marks/area.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,gBAAgB,EAOrB,MAAM,wBAAwB,CAAC;AAKhC,OAAO,KAAK,EACX,aAAa,EACb,UAAU,EACV,SAAS,EAET,UAAU,EAGV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,WAAW,CAAC,MAAM,CAAE,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IACpE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CACzB;AAmMD,sDAAsD;AACtD,wBAAgB,KAAK,CAAC,MAAM,EAC3B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,WAAW,CAAC,MAAM,CAAM,GAC/B,SAAS,CAEX;AAED,+CAA+C;AAC/C,wBAAgB,KAAK,CAAC,MAAM,EAC3B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,WAAW,CAAC,MAAM,CAAM,GAC/B,SAAS,CAEX"}
|
package/dist/core/marks/area.js
CHANGED
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
tips
|
|
14
14
|
} from "./shared.js";
|
|
15
15
|
import { stackSegments } from "./stack.js";
|
|
16
|
-
import {
|
|
16
|
+
import { POINTS_MOTION, pointsPath } from "../motion/points-motion.js";
|
|
17
|
+
import { linePath } from "../paths.js";
|
|
17
18
|
import { categoryKey } from "../scales/discrete.js";
|
|
18
19
|
const DEFAULT_FILL_OPACITY = 0.3;
|
|
19
20
|
const DEFAULT_STROKE_WIDTH = 2;
|
|
@@ -96,21 +97,23 @@ function areaMark(kind, data, options) {
|
|
|
96
97
|
data.length,
|
|
97
98
|
seriesOf
|
|
98
99
|
).values()) {
|
|
99
|
-
const runs = [
|
|
100
|
-
{ top: [], bottom: [] }
|
|
101
|
-
];
|
|
100
|
+
const runs = [[]];
|
|
102
101
|
for (const index of indices) {
|
|
103
102
|
const position = positions[index];
|
|
104
103
|
const edge = edges[index];
|
|
105
104
|
if (!isPlaceable(position) || edge === void 0) {
|
|
106
|
-
runs.push(
|
|
105
|
+
runs.push([]);
|
|
107
106
|
continue;
|
|
108
107
|
}
|
|
109
108
|
const along = positionScale.center(position);
|
|
110
109
|
const top = place(along, edge.high);
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const bottom = place(along, edge.low);
|
|
111
|
+
runs[runs.length - 1].push({
|
|
112
|
+
key: categoryKey(position),
|
|
113
|
+
...top,
|
|
114
|
+
x0: bottom.x,
|
|
115
|
+
y0: bottom.y
|
|
116
|
+
});
|
|
114
117
|
if (!tips(options.tip, data[index], index)) {
|
|
115
118
|
continue;
|
|
116
119
|
}
|
|
@@ -131,13 +134,23 @@ function areaMark(kind, data, options) {
|
|
|
131
134
|
value: vertical ? context.formatY(value) : context.formatX(value)
|
|
132
135
|
});
|
|
133
136
|
}
|
|
134
|
-
const shaped = runs.filter((run) => run.
|
|
137
|
+
const shaped = runs.filter((run) => run.length > 0);
|
|
138
|
+
const area = {
|
|
139
|
+
kind: "points",
|
|
140
|
+
runs: shaped,
|
|
141
|
+
shape: "area",
|
|
142
|
+
curve: options.curve
|
|
143
|
+
};
|
|
144
|
+
const enter = options.enter ?? "grow";
|
|
135
145
|
nodes.push({
|
|
136
146
|
kind: "path",
|
|
137
147
|
key: `${id}:area:${series.key}`,
|
|
138
148
|
series: series.key,
|
|
139
149
|
role: "mark",
|
|
140
|
-
d:
|
|
150
|
+
d: pointsPath(area),
|
|
151
|
+
geometry: area,
|
|
152
|
+
motion: POINTS_MOTION,
|
|
153
|
+
enter,
|
|
141
154
|
paint: paint({
|
|
142
155
|
fill: series.color,
|
|
143
156
|
fillOpacity: options.fillOpacity ?? DEFAULT_FILL_OPACITY,
|
|
@@ -150,7 +163,10 @@ function areaMark(kind, data, options) {
|
|
|
150
163
|
key: `${id}:line:${series.key}`,
|
|
151
164
|
series: series.key,
|
|
152
165
|
role: "mark",
|
|
153
|
-
d: shaped.map((run) => linePath(run
|
|
166
|
+
d: shaped.map((run) => linePath(run, options.curve)).join(""),
|
|
167
|
+
geometry: { ...area, shape: "line" },
|
|
168
|
+
motion: POINTS_MOTION,
|
|
169
|
+
enter,
|
|
154
170
|
paint: paint({
|
|
155
171
|
fill: "none",
|
|
156
172
|
stroke: series.color,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/core/marks/area.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tchannelLabel,\n\tisPlaceable,\n\tnumericValue,\n\treadChannel,\n} from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tgroupBySeries,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\ttips,\n} from \"#/core/marks/shared.ts\";\nimport { stackSegments } from \"#/core/marks/stack.ts\";\nimport {
|
|
5
|
-
"mappings": "AAAA;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP;AAAA,EAEC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,qBAAqB;AAC9B,SAAS,
|
|
4
|
+
"sourcesContent": ["import {\n\tchannelLabel,\n\tisPlaceable,\n\tnumericValue,\n\treadChannel,\n} from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tgroupBySeries,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\ttips,\n} from \"#/core/marks/shared.ts\";\nimport { stackSegments } from \"#/core/marks/stack.ts\";\nimport { POINTS_MOTION, pointsPath } from \"#/core/motion/points-motion.ts\";\nimport { type ChartXY, linePath } from \"#/core/paths.ts\";\nimport { categoryKey } from \"#/core/scales/discrete.ts\";\nimport type {\n\tChartAccessor,\n\tChartCurve,\n\tChartMark,\n\tChartPoint,\n\tChartValue,\n\tGeometryPoint,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface AreaOptions<TDatum> extends ChartMarkOptions<TDatum> {\n\treadonly x?: ChartAccessor<TDatum, ChartValue>;\n\treadonly y?: ChartAccessor<TDatum, ChartValue>;\n\t/** Explicit lower and upper edges: a confidence band, a min-max range. */\n\treadonly from?: ChartAccessor<TDatum, ChartValue>;\n\treadonly to?: ChartAccessor<TDatum, ChartValue>;\n\treadonly fill?: string;\n\treadonly fillOpacity?: number;\n\t/** Draw the upper edge as a line in the series colour. */\n\treadonly line?: boolean;\n\treadonly strokeWidth?: number;\n\treadonly strokeDasharray?: string;\n\treadonly curve?: ChartCurve;\n\t/** Series stack on one another. On by default when there is a color channel. */\n\treadonly stack?: boolean;\n}\n\nconst DEFAULT_FILL_OPACITY = 0.3;\nconst DEFAULT_STROKE_WIDTH = 2;\n\nfunction areaMark<TDatum>(\n\tkind: \"areaY\" | \"areaX\",\n\tdata: ReadonlyArray<TDatum>,\n\toptions: AreaOptions<TDatum>,\n): ChartMark {\n\tconst vertical = kind === \"areaY\";\n\tconst positionKey = vertical ? options.x : options.y;\n\tconst valueKey = vertical ? options.y : options.x;\n\tconst positions = readChannel(\n\t\tdata,\n\t\tpositionKey ?? ((_datum: TDatum, index: number) => index),\n\t);\n\tconst values = readChannel(\n\t\tdata,\n\t\tvalueKey ?? ((datum: TDatum) => datum as unknown as ChartValue),\n\t).map(numericValue);\n\tconst colors = colorChannel(data, options);\n\tconst explicit = options.from !== undefined && options.to !== undefined;\n\tconst froms = readChannel(data, options.from).map(numericValue);\n\tconst tos = readChannel(data, options.to).map(numericValue);\n\tconst stacked = !explicit && (options.stack ?? options.color !== undefined);\n\tconst segments = stacked\n\t\t? stackSegments(\n\t\t\t\tpositions.map((position) =>\n\t\t\t\t\tisPlaceable(position) ? categoryKey(position) : undefined,\n\t\t\t\t),\n\t\t\t\tvalues,\n\t\t\t)\n\t\t: [];\n\tconst edges = positions.map((position, index) => {\n\t\tif (!isPlaceable(position)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (explicit) {\n\t\t\tconst low = froms[index];\n\t\t\tconst high = tos[index];\n\t\t\treturn low === undefined || high === undefined\n\t\t\t\t? undefined\n\t\t\t\t: { low, high };\n\t\t}\n\t\tconst value = values[index];\n\t\tif (value === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn segments[index] ?? { low: 0, high: value };\n\t});\n\n\tconst positionChannel = {\n\t\tvalues: positions.filter(isPlaceable),\n\t\tlabel: channelLabel(positionKey),\n\t};\n\tconst valueChannel = {\n\t\tvalues: edges.flatMap((edge) => (edge ? [edge.low, edge.high] : [])),\n\t\tincludeZero: !explicit,\n\t\tlabel: channelLabel(valueKey) ?? options.label,\n\t};\n\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tfocusOrder: vertical ? \"x\" : \"y\",\n\t\tchannels: {\n\t\t\tx: vertical ? positionChannel : valueChannel,\n\t\t\ty: vertical ? valueChannel : positionChannel,\n\t\t\tcolor: colors.channel,\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, kind, context);\n\t\t\tconst positionScale = vertical ? context.scales.x : context.scales.y;\n\t\t\tconst valueScale = vertical ? context.scales.y : context.scales.x;\n\t\t\tif (positionScale === undefined || valueScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst seriesOf = seriesResolver(\n\t\t\t\tcolors.values,\n\t\t\t\t{ ...options, fixedColor: options.fill },\n\t\t\t\tid,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tfunction place(along: number, value: number): ChartXY {\n\t\t\t\tconst across = valueScale?.map(value) ?? 0;\n\t\t\t\treturn vertical ? { x: along, y: across } : { x: across, y: along };\n\t\t\t}\n\n\t\t\tconst nodes: SceneNode[] = [];\n\t\t\tconst points: ChartPoint[] = [];\n\t\t\tfor (const { series, indices } of groupBySeries(\n\t\t\t\tdata.length,\n\t\t\t\tseriesOf,\n\t\t\t).values()) {\n\t\t\t\tconst runs: GeometryPoint[][] = [[]];\n\t\t\t\tfor (const index of indices) {\n\t\t\t\t\tconst position = positions[index];\n\t\t\t\t\tconst edge = edges[index];\n\t\t\t\t\tif (!isPlaceable(position) || edge === undefined) {\n\t\t\t\t\t\truns.push([]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst along = positionScale.center(position);\n\t\t\t\t\tconst top = place(along, edge.high);\n\t\t\t\t\tconst bottom = place(along, edge.low);\n\t\t\t\t\truns[runs.length - 1].push({\n\t\t\t\t\t\tkey: categoryKey(position),\n\t\t\t\t\t\t...top,\n\t\t\t\t\t\tx0: bottom.x,\n\t\t\t\t\t\ty0: bottom.y,\n\t\t\t\t\t});\n\t\t\t\t\tif (!tips(options.tip, data[index], index)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst value = explicit ? edge.high : (values[index] ?? 0);\n\t\t\t\t\tpoints.push({\n\t\t\t\t\t\tkey: `${id}:${index}`,\n\t\t\t\t\t\tmarkId: id,\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tdatum: data[index],\n\t\t\t\t\t\tx: top.x,\n\t\t\t\t\t\ty: top.y,\n\t\t\t\t\t\txValue: vertical ? position : value,\n\t\t\t\t\t\tyValue: vertical ? value : position,\n\t\t\t\t\t\tseries: series.key,\n\t\t\t\t\t\tseriesLabel: series.label,\n\t\t\t\t\t\tcolor: series.color,\n\t\t\t\t\t\ttitle: vertical\n\t\t\t\t\t\t\t? context.formatX(position)\n\t\t\t\t\t\t\t: context.formatY(position),\n\t\t\t\t\t\tvalue: vertical ? context.formatY(value) : context.formatX(value),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst shaped = runs.filter((run) => run.length > 0);\n\t\t\t\tconst area = {\n\t\t\t\t\tkind: \"points\" as const,\n\t\t\t\t\truns: shaped,\n\t\t\t\t\tshape: \"area\" as const,\n\t\t\t\t\tcurve: options.curve,\n\t\t\t\t};\n\t\t\t\tconst enter = options.enter ?? \"grow\";\n\t\t\t\tnodes.push({\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: `${id}:area:${series.key}`,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\td: pointsPath(area),\n\t\t\t\t\tgeometry: area,\n\t\t\t\t\tmotion: POINTS_MOTION,\n\t\t\t\t\tenter,\n\t\t\t\t\tpaint: paint({\n\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\tfillOpacity: options.fillOpacity ?? DEFAULT_FILL_OPACITY,\n\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t\tif (options.line) {\n\t\t\t\t\tnodes.push({\n\t\t\t\t\t\tkind: \"path\",\n\t\t\t\t\t\tkey: `${id}:line:${series.key}`,\n\t\t\t\t\t\tseries: series.key,\n\t\t\t\t\t\trole: \"mark\",\n\t\t\t\t\t\td: shaped.map((run) => linePath(run, options.curve)).join(\"\"),\n\t\t\t\t\t\tgeometry: { ...area, shape: \"line\" },\n\t\t\t\t\t\tmotion: POINTS_MOTION,\n\t\t\t\t\t\tenter,\n\t\t\t\t\t\tpaint: paint({\n\t\t\t\t\t\t\tfill: \"none\",\n\t\t\t\t\t\t\tstroke: series.color,\n\t\t\t\t\t\t\tstrokeWidth: options.strokeWidth ?? DEFAULT_STROKE_WIDTH,\n\t\t\t\t\t\t\tstrokeDasharray: options.strokeDasharray,\n\t\t\t\t\t\t\tstrokeLinecap: \"round\",\n\t\t\t\t\t\t\tstrokeLinejoin: \"round\",\n\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst legend =\n\t\t\t\toptions.color === undefined && options.label !== undefined\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkey: id,\n\t\t\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\t\t\tcolor: options.fill ?? context.paletteColor(context.markIndex),\n\t\t\t\t\t\t\t\tshape: \"square\" as const,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\treturn { nodes, points, legend };\n\t\t},\n\t};\n}\n\n/** A filled band under a series, over x positions. */\nexport function areaY<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: AreaOptions<TDatum> = {},\n): ChartMark {\n\treturn areaMark(\"areaY\", data, options);\n}\n\n/** A filled band along x, over y positions. */\nexport function areaX<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: AreaOptions<TDatum> = {},\n): ChartMark {\n\treturn areaMark(\"areaX\", data, options);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar.d.ts","sourceRoot":"","sources":["../../../src/core/marks/bar.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,gBAAgB,EAMrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EACX,aAAa,EAEb,SAAS,EAET,UAAU,EAEV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,UAAU,CAAC,MAAM,CAAE,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IACnE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAC/D;
|
|
1
|
+
{"version":3,"file":"bar.d.ts","sourceRoot":"","sources":["../../../src/core/marks/bar.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,KAAK,gBAAgB,EAMrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EACX,aAAa,EAEb,SAAS,EAET,UAAU,EAEV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,UAAU,CAAC,MAAM,CAAE,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IACnE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,8FAA8F;IAC9F,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAC/D;AA0OD,qDAAqD;AACrD,wBAAgB,IAAI,CAAC,MAAM,EAC1B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,UAAU,CAAC,MAAM,CAAM,GAC9B,SAAS,CAEX;AAED,6DAA6D;AAC7D,wBAAgB,IAAI,CAAC,MAAM,EAC1B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,UAAU,CAAC,MAAM,CAAM,GAC9B,SAAS,CAEX"}
|
package/dist/core/marks/bar.js
CHANGED
|
@@ -134,6 +134,8 @@ function barMark(kind, data, options) {
|
|
|
134
134
|
role: "mark",
|
|
135
135
|
...rect,
|
|
136
136
|
corners: corners(vertical, bar, radius, explicit),
|
|
137
|
+
baseline: { axis: vertical ? "y" : "x", at: lowPixel },
|
|
138
|
+
enter: options.enter ?? "grow",
|
|
137
139
|
paint: paint(
|
|
138
140
|
options.projected?.(data[bar.index], bar.index) ? {
|
|
139
141
|
fill: series.color,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/core/marks/bar.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tchannelLabel,\n\tisPlaceable,\n\tnumericValue,\n\treadChannel,\n} from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\ttips,\n} from \"#/core/marks/shared.ts\";\nimport { stackSegments } from \"#/core/marks/stack.ts\";\nimport { categoryKey } from \"#/core/scales/discrete.ts\";\nimport type {\n\tChartAccessor,\n\tChartCorners,\n\tChartMark,\n\tChartPoint,\n\tChartValue,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface BarOptions<TDatum> extends ChartMarkOptions<TDatum> {\n\treadonly x?: ChartAccessor<TDatum, ChartValue>;\n\treadonly y?: ChartAccessor<TDatum, ChartValue>;\n\t/** Explicit start and end of the bar on the value axis: floating bars, ranges, Gantt rows. */\n\treadonly from?: ChartAccessor<TDatum, ChartValue>;\n\treadonly to?: ChartAccessor<TDatum, ChartValue>;\n\treadonly fill?: string;\n\treadonly fillOpacity?: number;\n\treadonly stroke?: string;\n\treadonly strokeDasharray?: string;\n\t/** Series stack on one another. On by default when there is a color channel. */\n\treadonly stack?: boolean;\n\t/** Series stand side by side inside the band instead of stacking. */\n\treadonly group?: boolean;\n\t/** Corner radius of the bar's far end. */\n\treadonly radius?: number;\n\t/** Pixels kept clear on each side of the bar inside its band. */\n\treadonly inset?: number;\n\t/**\n\t * Bars to draw hatched and outlined: projections, stages still in flight,\n\t * anything pencilled in rather than recorded.\n\t */\n\treadonly projected?: (datum: TDatum, index: number) => boolean;\n}\n\nconst DEFAULT_RADIUS = 4;\n\ninterface BarDatum {\n\treadonly index: number;\n\treadonly position: ChartValue;\n\treadonly low: number;\n\treadonly high: number;\n\treadonly value: number;\n\t/** Round the far end: the outer segment of a stack, or any unstacked bar. */\n\treadonly outer: boolean;\n}\n\nfunction barMark<TDatum>(\n\tkind: \"barY\" | \"barX\",\n\tdata: ReadonlyArray<TDatum>,\n\toptions: BarOptions<TDatum>,\n): ChartMark {\n\tconst vertical = kind === \"barY\";\n\tconst positionKey = vertical ? options.x : options.y;\n\tconst valueKey = vertical ? options.y : options.x;\n\tconst positions = readChannel(\n\t\tdata,\n\t\tpositionKey ?? ((_datum: TDatum, index: number) => index),\n\t);\n\tconst values = readChannel(\n\t\tdata,\n\t\tvalueKey ?? ((datum: TDatum) => datum as unknown as ChartValue),\n\t).map(numericValue);\n\tconst colors = colorChannel(data, options);\n\tconst explicit = options.from !== undefined && options.to !== undefined;\n\tconst froms = readChannel(data, options.from).map(numericValue);\n\tconst tos = readChannel(data, options.to).map(numericValue);\n\tconst stacked =\n\t\t!explicit &&\n\t\t!options.group &&\n\t\t(options.stack ?? options.color !== undefined);\n\tconst segments = stacked\n\t\t? stackSegments(\n\t\t\t\tpositions.map((position) =>\n\t\t\t\t\tisPlaceable(position) ? categoryKey(position) : undefined,\n\t\t\t\t),\n\t\t\t\tvalues,\n\t\t\t)\n\t\t: [];\n\n\tconst bars: BarDatum[] = [];\n\tfor (const [index, position] of positions.entries()) {\n\t\tif (!isPlaceable(position)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (explicit) {\n\t\t\tconst low = froms[index];\n\t\t\tconst high = tos[index];\n\t\t\tif (low !== undefined && high !== undefined) {\n\t\t\t\tbars.push({\n\t\t\t\t\tindex,\n\t\t\t\t\tposition,\n\t\t\t\t\tlow,\n\t\t\t\t\thigh,\n\t\t\t\t\tvalue: high - low,\n\t\t\t\t\touter: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst value = values[index];\n\t\tif (value === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst segment = segments[index];\n\t\tbars.push(\n\t\t\tsegment === undefined\n\t\t\t\t? { index, position, low: 0, high: value, value, outer: true }\n\t\t\t\t: { index, position, ...segment, value },\n\t\t);\n\t}\n\n\tconst positionChannel = {\n\t\tvalues: bars.map((bar) => bar.position),\n\t\tdiscrete: \"band\" as const,\n\t\tlabel: channelLabel(positionKey),\n\t};\n\tconst valueChannel = {\n\t\tvalues: bars.flatMap((bar) => [bar.low, bar.high]),\n\t\tincludeZero: !explicit,\n\t\tlabel: channelLabel(valueKey) ?? options.label,\n\t};\n\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tfocusOrder: vertical ? \"x\" : \"y\",\n\t\tchannels: {\n\t\t\tx: vertical ? positionChannel : valueChannel,\n\t\t\ty: vertical ? valueChannel : positionChannel,\n\t\t\tcolor: colors.channel,\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, kind, context);\n\t\t\tconst positionScale = vertical ? context.scales.x : context.scales.y;\n\t\t\tconst valueScale = vertical ? context.scales.y : context.scales.x;\n\t\t\tif (positionScale === undefined || valueScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst seriesOf = seriesResolver(\n\t\t\t\tcolors.values,\n\t\t\t\t{ ...options, fixedColor: options.fill },\n\t\t\t\tid,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tconst seriesOrder = [\n\t\t\t\t...new Set(bars.map((bar) => seriesOf(bar.index).key)),\n\t\t\t];\n\t\t\tconst lanes = options.group ? Math.max(1, seriesOrder.length) : 1;\n\t\t\tconst laneWidth = positionScale.bandwidth / lanes;\n\t\t\tconst inset = options.inset ?? 0;\n\t\t\tconst radius = options.radius ?? DEFAULT_RADIUS;\n\n\t\t\tconst nodes: SceneNode[] = [];\n\t\t\tconst points: ChartPoint[] = [];\n\t\t\tfor (const bar of bars) {\n\t\t\t\tconst series = seriesOf(bar.index);\n\t\t\t\tconst lane = options.group ? seriesOrder.indexOf(series.key) : 0;\n\t\t\t\tconst alongStart =\n\t\t\t\t\tpositionScale.map(bar.position) + lane * laneWidth + inset;\n\t\t\t\tconst alongSize = Math.max(0, laneWidth - inset * 2);\n\t\t\t\tconst lowPixel = valueScale.map(bar.low);\n\t\t\t\tconst highPixel = valueScale.map(bar.high);\n\t\t\t\tconst acrossStart = Math.min(lowPixel, highPixel);\n\t\t\t\tconst acrossSize = Math.abs(highPixel - lowPixel);\n\t\t\t\tconst rect = vertical\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tx: alongStart,\n\t\t\t\t\t\t\ty: acrossStart,\n\t\t\t\t\t\t\twidth: alongSize,\n\t\t\t\t\t\t\theight: acrossSize,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tx: acrossStart,\n\t\t\t\t\t\t\ty: alongStart,\n\t\t\t\t\t\t\twidth: acrossSize,\n\t\t\t\t\t\t\theight: alongSize,\n\t\t\t\t\t\t};\n\t\t\t\tnodes.push({\n\t\t\t\t\tkind: \"rect\",\n\t\t\t\t\tkey: `${id}:${bar.index}`,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\t...rect,\n\t\t\t\t\tcorners: corners(vertical, bar, radius, explicit),\n\t\t\t\t\tpaint: paint(\n\t\t\t\t\t\toptions.projected?.(data[bar.index], bar.index)\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\t\t\t\thatch: true,\n\t\t\t\t\t\t\t\t\tstroke: series.color,\n\t\t\t\t\t\t\t\t\tstrokeWidth: 1,\n\t\t\t\t\t\t\t\t\tstrokeDasharray: \"3 2\",\n\t\t\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\t\t\t\tfillOpacity: options.fillOpacity,\n\t\t\t\t\t\t\t\t\tstroke: options.stroke,\n\t\t\t\t\t\t\t\t\tstrokeDasharray: options.strokeDasharray,\n\t\t\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tif (!tips(options.tip, data[bar.index], bar.index)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst along = alongStart + alongSize / 2;\n\t\t\t\tpoints.push({\n\t\t\t\t\tkey: `${id}:${bar.index}`,\n\t\t\t\t\tmarkId: id,\n\t\t\t\t\tindex: bar.index,\n\t\t\t\t\tdatum: data[bar.index],\n\t\t\t\t\tx: vertical ? along : highPixel,\n\t\t\t\t\ty: vertical ? highPixel : along,\n\t\t\t\t\txValue: vertical ? bar.position : bar.value,\n\t\t\t\t\tyValue: vertical ? bar.value : bar.position,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\tseriesLabel: series.label,\n\t\t\t\t\tcolor: series.color,\n\t\t\t\t\ttitle: vertical\n\t\t\t\t\t\t? context.formatX(bar.position)\n\t\t\t\t\t\t: context.formatY(bar.position),\n\t\t\t\t\tvalue: vertical\n\t\t\t\t\t\t? context.formatY(bar.value)\n\t\t\t\t\t\t: context.formatX(bar.value),\n\t\t\t\t\thit: { kind: \"rect\", rect },\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst legend =\n\t\t\t\toptions.color === undefined && options.label !== undefined\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkey: id,\n\t\t\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\t\t\tcolor: options.fill ?? context.paletteColor(context.markIndex),\n\t\t\t\t\t\t\t\tshape: \"square\" as const,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\treturn { nodes, points, legend };\n\t\t},\n\t};\n}\n\n/** Rounds the end of the bar away from zero, and only that end: stacked joins stay square. */\nfunction corners(\n\tvertical: boolean,\n\tbar: BarDatum,\n\tradius: number,\n\texplicit: boolean,\n): ChartCorners | undefined {\n\tif (radius === 0 || !bar.outer) {\n\t\treturn undefined;\n\t}\n\tif (explicit) {\n\t\treturn [radius, radius, radius, radius];\n\t}\n\tconst positive = bar.high >= bar.low;\n\tif (vertical) {\n\t\treturn positive ? [radius, radius, 0, 0] : [0, 0, radius, radius];\n\t}\n\treturn positive ? [0, radius, radius, 0] : [radius, 0, 0, radius];\n}\n\n/** Upright bars: categories along x, values up y. */\nexport function barY<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: BarOptions<TDatum> = {},\n): ChartMark {\n\treturn barMark(\"barY\", data, options);\n}\n\n/** Bars on their side: categories down y, values along x. */\nexport function barX<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: BarOptions<TDatum> = {},\n): ChartMark {\n\treturn barMark(\"barX\", data, options);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tchannelLabel,\n\tisPlaceable,\n\tnumericValue,\n\treadChannel,\n} from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\ttips,\n} from \"#/core/marks/shared.ts\";\nimport { stackSegments } from \"#/core/marks/stack.ts\";\nimport { categoryKey } from \"#/core/scales/discrete.ts\";\nimport type {\n\tChartAccessor,\n\tChartCorners,\n\tChartMark,\n\tChartPoint,\n\tChartValue,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface BarOptions<TDatum> extends ChartMarkOptions<TDatum> {\n\treadonly x?: ChartAccessor<TDatum, ChartValue>;\n\treadonly y?: ChartAccessor<TDatum, ChartValue>;\n\t/** Explicit start and end of the bar on the value axis: floating bars, ranges, Gantt rows. */\n\treadonly from?: ChartAccessor<TDatum, ChartValue>;\n\treadonly to?: ChartAccessor<TDatum, ChartValue>;\n\treadonly fill?: string;\n\treadonly fillOpacity?: number;\n\treadonly stroke?: string;\n\treadonly strokeDasharray?: string;\n\t/** Series stack on one another. On by default when there is a color channel. */\n\treadonly stack?: boolean;\n\t/** Series stand side by side inside the band instead of stacking. */\n\treadonly group?: boolean;\n\t/** Corner radius of the bar's far end. */\n\treadonly radius?: number;\n\t/** Pixels kept clear on each side of the bar inside its band. */\n\treadonly inset?: number;\n\t/**\n\t * Bars to draw hatched and outlined: projections, stages still in flight,\n\t * anything pencilled in rather than recorded.\n\t */\n\treadonly projected?: (datum: TDatum, index: number) => boolean;\n}\n\nconst DEFAULT_RADIUS = 4;\n\ninterface BarDatum {\n\treadonly index: number;\n\treadonly position: ChartValue;\n\treadonly low: number;\n\treadonly high: number;\n\treadonly value: number;\n\t/** Round the far end: the outer segment of a stack, or any unstacked bar. */\n\treadonly outer: boolean;\n}\n\nfunction barMark<TDatum>(\n\tkind: \"barY\" | \"barX\",\n\tdata: ReadonlyArray<TDatum>,\n\toptions: BarOptions<TDatum>,\n): ChartMark {\n\tconst vertical = kind === \"barY\";\n\tconst positionKey = vertical ? options.x : options.y;\n\tconst valueKey = vertical ? options.y : options.x;\n\tconst positions = readChannel(\n\t\tdata,\n\t\tpositionKey ?? ((_datum: TDatum, index: number) => index),\n\t);\n\tconst values = readChannel(\n\t\tdata,\n\t\tvalueKey ?? ((datum: TDatum) => datum as unknown as ChartValue),\n\t).map(numericValue);\n\tconst colors = colorChannel(data, options);\n\tconst explicit = options.from !== undefined && options.to !== undefined;\n\tconst froms = readChannel(data, options.from).map(numericValue);\n\tconst tos = readChannel(data, options.to).map(numericValue);\n\tconst stacked =\n\t\t!explicit &&\n\t\t!options.group &&\n\t\t(options.stack ?? options.color !== undefined);\n\tconst segments = stacked\n\t\t? stackSegments(\n\t\t\t\tpositions.map((position) =>\n\t\t\t\t\tisPlaceable(position) ? categoryKey(position) : undefined,\n\t\t\t\t),\n\t\t\t\tvalues,\n\t\t\t)\n\t\t: [];\n\n\tconst bars: BarDatum[] = [];\n\tfor (const [index, position] of positions.entries()) {\n\t\tif (!isPlaceable(position)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (explicit) {\n\t\t\tconst low = froms[index];\n\t\t\tconst high = tos[index];\n\t\t\tif (low !== undefined && high !== undefined) {\n\t\t\t\tbars.push({\n\t\t\t\t\tindex,\n\t\t\t\t\tposition,\n\t\t\t\t\tlow,\n\t\t\t\t\thigh,\n\t\t\t\t\tvalue: high - low,\n\t\t\t\t\touter: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst value = values[index];\n\t\tif (value === undefined) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst segment = segments[index];\n\t\tbars.push(\n\t\t\tsegment === undefined\n\t\t\t\t? { index, position, low: 0, high: value, value, outer: true }\n\t\t\t\t: { index, position, ...segment, value },\n\t\t);\n\t}\n\n\tconst positionChannel = {\n\t\tvalues: bars.map((bar) => bar.position),\n\t\tdiscrete: \"band\" as const,\n\t\tlabel: channelLabel(positionKey),\n\t};\n\tconst valueChannel = {\n\t\tvalues: bars.flatMap((bar) => [bar.low, bar.high]),\n\t\tincludeZero: !explicit,\n\t\tlabel: channelLabel(valueKey) ?? options.label,\n\t};\n\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tfocusOrder: vertical ? \"x\" : \"y\",\n\t\tchannels: {\n\t\t\tx: vertical ? positionChannel : valueChannel,\n\t\t\ty: vertical ? valueChannel : positionChannel,\n\t\t\tcolor: colors.channel,\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, kind, context);\n\t\t\tconst positionScale = vertical ? context.scales.x : context.scales.y;\n\t\t\tconst valueScale = vertical ? context.scales.y : context.scales.x;\n\t\t\tif (positionScale === undefined || valueScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst seriesOf = seriesResolver(\n\t\t\t\tcolors.values,\n\t\t\t\t{ ...options, fixedColor: options.fill },\n\t\t\t\tid,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tconst seriesOrder = [\n\t\t\t\t...new Set(bars.map((bar) => seriesOf(bar.index).key)),\n\t\t\t];\n\t\t\tconst lanes = options.group ? Math.max(1, seriesOrder.length) : 1;\n\t\t\tconst laneWidth = positionScale.bandwidth / lanes;\n\t\t\tconst inset = options.inset ?? 0;\n\t\t\tconst radius = options.radius ?? DEFAULT_RADIUS;\n\n\t\t\tconst nodes: SceneNode[] = [];\n\t\t\tconst points: ChartPoint[] = [];\n\t\t\tfor (const bar of bars) {\n\t\t\t\tconst series = seriesOf(bar.index);\n\t\t\t\tconst lane = options.group ? seriesOrder.indexOf(series.key) : 0;\n\t\t\t\tconst alongStart =\n\t\t\t\t\tpositionScale.map(bar.position) + lane * laneWidth + inset;\n\t\t\t\tconst alongSize = Math.max(0, laneWidth - inset * 2);\n\t\t\t\tconst lowPixel = valueScale.map(bar.low);\n\t\t\t\tconst highPixel = valueScale.map(bar.high);\n\t\t\t\tconst acrossStart = Math.min(lowPixel, highPixel);\n\t\t\t\tconst acrossSize = Math.abs(highPixel - lowPixel);\n\t\t\t\tconst rect = vertical\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tx: alongStart,\n\t\t\t\t\t\t\ty: acrossStart,\n\t\t\t\t\t\t\twidth: alongSize,\n\t\t\t\t\t\t\theight: acrossSize,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tx: acrossStart,\n\t\t\t\t\t\t\ty: alongStart,\n\t\t\t\t\t\t\twidth: acrossSize,\n\t\t\t\t\t\t\theight: alongSize,\n\t\t\t\t\t\t};\n\t\t\t\tnodes.push({\n\t\t\t\t\tkind: \"rect\",\n\t\t\t\t\tkey: `${id}:${bar.index}`,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\t...rect,\n\t\t\t\t\tcorners: corners(vertical, bar, radius, explicit),\n\t\t\t\t\tbaseline: { axis: vertical ? \"y\" : \"x\", at: lowPixel },\n\t\t\t\t\tenter: options.enter ?? \"grow\",\n\t\t\t\t\tpaint: paint(\n\t\t\t\t\t\toptions.projected?.(data[bar.index], bar.index)\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\t\t\t\thatch: true,\n\t\t\t\t\t\t\t\t\tstroke: series.color,\n\t\t\t\t\t\t\t\t\tstrokeWidth: 1,\n\t\t\t\t\t\t\t\t\tstrokeDasharray: \"3 2\",\n\t\t\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\t\t\t\tfillOpacity: options.fillOpacity,\n\t\t\t\t\t\t\t\t\tstroke: options.stroke,\n\t\t\t\t\t\t\t\t\tstrokeDasharray: options.strokeDasharray,\n\t\t\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tif (!tips(options.tip, data[bar.index], bar.index)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst along = alongStart + alongSize / 2;\n\t\t\t\tpoints.push({\n\t\t\t\t\tkey: `${id}:${bar.index}`,\n\t\t\t\t\tmarkId: id,\n\t\t\t\t\tindex: bar.index,\n\t\t\t\t\tdatum: data[bar.index],\n\t\t\t\t\tx: vertical ? along : highPixel,\n\t\t\t\t\ty: vertical ? highPixel : along,\n\t\t\t\t\txValue: vertical ? bar.position : bar.value,\n\t\t\t\t\tyValue: vertical ? bar.value : bar.position,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\tseriesLabel: series.label,\n\t\t\t\t\tcolor: series.color,\n\t\t\t\t\ttitle: vertical\n\t\t\t\t\t\t? context.formatX(bar.position)\n\t\t\t\t\t\t: context.formatY(bar.position),\n\t\t\t\t\tvalue: vertical\n\t\t\t\t\t\t? context.formatY(bar.value)\n\t\t\t\t\t\t: context.formatX(bar.value),\n\t\t\t\t\thit: { kind: \"rect\", rect },\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst legend =\n\t\t\t\toptions.color === undefined && options.label !== undefined\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkey: id,\n\t\t\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\t\t\tcolor: options.fill ?? context.paletteColor(context.markIndex),\n\t\t\t\t\t\t\t\tshape: \"square\" as const,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\treturn { nodes, points, legend };\n\t\t},\n\t};\n}\n\n/** Rounds the end of the bar away from zero, and only that end: stacked joins stay square. */\nfunction corners(\n\tvertical: boolean,\n\tbar: BarDatum,\n\tradius: number,\n\texplicit: boolean,\n): ChartCorners | undefined {\n\tif (radius === 0 || !bar.outer) {\n\t\treturn undefined;\n\t}\n\tif (explicit) {\n\t\treturn [radius, radius, radius, radius];\n\t}\n\tconst positive = bar.high >= bar.low;\n\tif (vertical) {\n\t\treturn positive ? [radius, radius, 0, 0] : [0, 0, radius, radius];\n\t}\n\treturn positive ? [0, radius, radius, 0] : [radius, 0, 0, radius];\n}\n\n/** Upright bars: categories along x, values up y. */\nexport function barY<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: BarOptions<TDatum> = {},\n): ChartMark {\n\treturn barMark(\"barY\", data, options);\n}\n\n/** Bars on their side: categories down y, values along x. */\nexport function barX<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: BarOptions<TDatum> = {},\n): ChartMark {\n\treturn barMark(\"barX\", data, options);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../../src/core/marks/line.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAQrB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../../src/core/marks/line.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAQrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EACX,aAAa,EACb,UAAU,EACV,SAAS,EAET,UAAU,EAGV,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,WAAW,CAAC,MAAM,CAAE,SAAQ,gBAAgB,CAAC,MAAM,CAAC;IACpE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACxB;AAuKD,8EAA8E;AAC9E,wBAAgB,KAAK,CAAC,MAAM,EAC3B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,WAAW,CAAC,MAAM,CAAM,GAC/B,SAAS,CAEX;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,MAAM,EAC3B,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,OAAO,GAAE,WAAW,CAAC,MAAM,CAAM,GAC/B,SAAS,CAEX"}
|
package/dist/core/marks/line.js
CHANGED
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
tips,
|
|
9
9
|
valueOn
|
|
10
10
|
} from "./shared.js";
|
|
11
|
-
import {
|
|
11
|
+
import { POINTS_MOTION, pointsPath } from "../motion/points-motion.js";
|
|
12
|
+
import { categoryKey } from "../scales/discrete.js";
|
|
12
13
|
const DEFAULT_STROKE_WIDTH = 2;
|
|
13
14
|
const DOT_RADIUS = 3;
|
|
14
15
|
function positionAccessor(accessor, fallback) {
|
|
@@ -72,7 +73,7 @@ function lineMark(kind, data, options) {
|
|
|
72
73
|
const along = positionScale.center(position);
|
|
73
74
|
const across = valueScale.center(value);
|
|
74
75
|
const xy = vertical ? { x: along, y: across } : { x: across, y: along };
|
|
75
|
-
runs[runs.length - 1].push(xy);
|
|
76
|
+
runs[runs.length - 1].push({ key: categoryKey(position), ...xy });
|
|
76
77
|
if (tips(options.tip, data[index], index)) {
|
|
77
78
|
points.push({
|
|
78
79
|
key: `${id}:${index}`,
|
|
@@ -108,13 +109,21 @@ function lineMark(kind, data, options) {
|
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
|
-
const
|
|
112
|
+
const geometry = {
|
|
113
|
+
kind: "points",
|
|
114
|
+
runs: runs.filter((run) => run.length > 1),
|
|
115
|
+
shape: "line",
|
|
116
|
+
curve: options.curve
|
|
117
|
+
};
|
|
112
118
|
lines.push({
|
|
113
119
|
kind: "path",
|
|
114
120
|
key: `${id}:line:${series.key}`,
|
|
115
121
|
series: series.key,
|
|
116
122
|
role: "mark",
|
|
117
|
-
d,
|
|
123
|
+
d: pointsPath(geometry),
|
|
124
|
+
geometry,
|
|
125
|
+
motion: POINTS_MOTION,
|
|
126
|
+
enter: options.enter,
|
|
118
127
|
paint: paint({
|
|
119
128
|
stroke: series.color,
|
|
120
129
|
strokeWidth: options.strokeWidth ?? DEFAULT_STROKE_WIDTH,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/core/marks/line.ts"],
|
|
4
|
-
"sourcesContent": ["import { channelLabel, isPlaceable, readChannel } from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tgroupBySeries,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\ttips,\n\tvalueOn,\n} from \"#/core/marks/shared.ts\";\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAS,cAAc,aAAa,mBAAmB;AACvD;AAAA,EAEC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,
|
|
4
|
+
"sourcesContent": ["import { channelLabel, isPlaceable, readChannel } from \"#/core/channel.ts\";\nimport {\n\ttype ChartMarkOptions,\n\tcolorChannel,\n\tgroupBySeries,\n\tmarkId,\n\tpaint,\n\tseriesResolver,\n\ttips,\n\tvalueOn,\n} from \"#/core/marks/shared.ts\";\nimport { POINTS_MOTION, pointsPath } from \"#/core/motion/points-motion.ts\";\nimport { categoryKey } from \"#/core/scales/discrete.ts\";\nimport type {\n\tChartAccessor,\n\tChartCurve,\n\tChartMark,\n\tChartPoint,\n\tChartValue,\n\tGeometryPoint,\n\tSceneNode,\n} from \"#/core/types.ts\";\n\nexport interface LineOptions<TDatum> extends ChartMarkOptions<TDatum> {\n\treadonly x?: ChartAccessor<TDatum, ChartValue>;\n\treadonly y?: ChartAccessor<TDatum, ChartValue>;\n\treadonly stroke?: string;\n\treadonly strokeWidth?: number;\n\treadonly strokeDasharray?: string;\n\treadonly curve?: ChartCurve;\n\t/** A dot on every point, not only on the focused one. */\n\treadonly dots?: boolean;\n}\n\nconst DEFAULT_STROKE_WIDTH = 2;\nconst DOT_RADIUS = 3;\n\n/** With no accessor, a line of plain numbers plots each against its index. */\nfunction positionAccessor<TDatum>(\n\taccessor: ChartAccessor<TDatum, ChartValue> | undefined,\n\tfallback: \"index\" | \"identity\",\n): ChartAccessor<TDatum, ChartValue> {\n\tif (accessor !== undefined) {\n\t\treturn accessor;\n\t}\n\treturn fallback === \"index\"\n\t\t? (_datum, index) => index\n\t\t: (datum) => datum as unknown as ChartValue;\n}\n\nfunction lineMark<TDatum>(\n\tkind: \"lineY\" | \"lineX\",\n\tdata: ReadonlyArray<TDatum>,\n\toptions: LineOptions<TDatum>,\n): ChartMark {\n\t// lineY: the value runs up the y axis; lineX: along x, positions down y.\n\tconst vertical = kind === \"lineY\";\n\tconst positionKey = vertical ? options.x : options.y;\n\tconst valueKey = vertical ? options.y : options.x;\n\tconst positions = readChannel(data, positionAccessor(positionKey, \"index\"));\n\tconst values = readChannel(data, positionAccessor(valueKey, \"identity\"));\n\tconst colors = colorChannel(data, options);\n\tconst positionChannel = {\n\t\tvalues: positions.filter(isPlaceable),\n\t\tlabel: channelLabel(positionKey),\n\t};\n\tconst valueChannel = {\n\t\tvalues: values.filter(isPlaceable),\n\t\tlabel: channelLabel(valueKey) ?? options.label,\n\t};\n\n\treturn {\n\t\tid: options.id,\n\t\tcoordinate: \"cartesian\",\n\t\tfocusOrder: vertical ? \"x\" : \"y\",\n\t\tchannels: {\n\t\t\tx: vertical ? positionChannel : valueChannel,\n\t\t\ty: vertical ? valueChannel : positionChannel,\n\t\t\tcolor: colors.channel,\n\t\t},\n\t\trender(context) {\n\t\t\tconst id = markId(options.id, kind, context);\n\t\t\tconst positionScale = vertical ? context.scales.x : context.scales.y;\n\t\t\tconst valueScale = vertical ? context.scales.y : context.scales.x;\n\t\t\tif (positionScale === undefined || valueScale === undefined) {\n\t\t\t\treturn { nodes: [] };\n\t\t\t}\n\t\t\tconst seriesOf = seriesResolver(\n\t\t\t\tcolors.values,\n\t\t\t\t{ ...options, fixedColor: options.stroke },\n\t\t\t\tid,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tconst lines: SceneNode[] = [];\n\t\t\tconst dots: SceneNode[] = [];\n\t\t\tconst points: ChartPoint[] = [];\n\n\t\t\tfor (const { series, indices } of groupBySeries(\n\t\t\t\tdata.length,\n\t\t\t\tseriesOf,\n\t\t\t).values()) {\n\t\t\t\t// A gap in the data is a gap in the line, not a dive to zero.\n\t\t\t\tconst runs: GeometryPoint[][] = [[]];\n\t\t\t\tfor (const index of indices) {\n\t\t\t\t\tconst position = positions[index];\n\t\t\t\t\tconst value = valueOn(valueScale, values[index]);\n\t\t\t\t\tif (!isPlaceable(position) || value === undefined) {\n\t\t\t\t\t\truns.push([]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst along = positionScale.center(position);\n\t\t\t\t\tconst across = valueScale.center(value);\n\t\t\t\t\tconst xy = vertical\n\t\t\t\t\t\t? { x: along, y: across }\n\t\t\t\t\t\t: { x: across, y: along };\n\t\t\t\t\truns[runs.length - 1].push({ key: categoryKey(position), ...xy });\n\t\t\t\t\tif (tips(options.tip, data[index], index)) {\n\t\t\t\t\t\tpoints.push({\n\t\t\t\t\t\t\tkey: `${id}:${index}`,\n\t\t\t\t\t\t\tmarkId: id,\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tdatum: data[index],\n\t\t\t\t\t\t\tx: xy.x,\n\t\t\t\t\t\t\ty: xy.y,\n\t\t\t\t\t\t\txValue: vertical ? position : value,\n\t\t\t\t\t\t\tyValue: vertical ? value : position,\n\t\t\t\t\t\t\tseries: series.key,\n\t\t\t\t\t\t\tseriesLabel: series.label,\n\t\t\t\t\t\t\tcolor: series.color,\n\t\t\t\t\t\t\ttitle: vertical\n\t\t\t\t\t\t\t\t? context.formatX(position)\n\t\t\t\t\t\t\t\t: context.formatY(position),\n\t\t\t\t\t\t\tvalue: vertical ? context.formatY(value) : context.formatX(value),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (options.dots) {\n\t\t\t\t\t\tdots.push({\n\t\t\t\t\t\t\tkind: \"circle\",\n\t\t\t\t\t\t\tkey: `${id}:dot:${index}`,\n\t\t\t\t\t\t\tseries: series.key,\n\t\t\t\t\t\t\trole: \"mark\",\n\t\t\t\t\t\t\tcx: xy.x,\n\t\t\t\t\t\t\tcy: xy.y,\n\t\t\t\t\t\t\tr: DOT_RADIUS,\n\t\t\t\t\t\t\tpaint: paint({\n\t\t\t\t\t\t\t\tfill: series.color,\n\t\t\t\t\t\t\t\tstroke: context.theme.background,\n\t\t\t\t\t\t\t\tstrokeWidth: 1.5,\n\t\t\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst geometry = {\n\t\t\t\t\tkind: \"points\" as const,\n\t\t\t\t\truns: runs.filter((run) => run.length > 1),\n\t\t\t\t\tshape: \"line\" as const,\n\t\t\t\t\tcurve: options.curve,\n\t\t\t\t};\n\t\t\t\tlines.push({\n\t\t\t\t\tkind: \"path\",\n\t\t\t\t\tkey: `${id}:line:${series.key}`,\n\t\t\t\t\tseries: series.key,\n\t\t\t\t\trole: \"mark\",\n\t\t\t\t\td: pointsPath(geometry),\n\t\t\t\t\tgeometry,\n\t\t\t\t\tmotion: POINTS_MOTION,\n\t\t\t\t\tenter: options.enter,\n\t\t\t\t\tpaint: paint({\n\t\t\t\t\t\tstroke: series.color,\n\t\t\t\t\t\tstrokeWidth: options.strokeWidth ?? DEFAULT_STROKE_WIDTH,\n\t\t\t\t\t\tstrokeDasharray: options.strokeDasharray,\n\t\t\t\t\t\tstrokeLinecap: \"round\",\n\t\t\t\t\t\tstrokeLinejoin: \"round\",\n\t\t\t\t\t\tfill: \"none\",\n\t\t\t\t\t\topacity: options.opacity,\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst legend =\n\t\t\t\toptions.color === undefined && options.label !== undefined\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tkey: id,\n\t\t\t\t\t\t\t\tlabel: options.label,\n\t\t\t\t\t\t\t\tcolor:\n\t\t\t\t\t\t\t\t\toptions.stroke ?? context.paletteColor(context.markIndex),\n\t\t\t\t\t\t\t\tshape: options.strokeDasharray\n\t\t\t\t\t\t\t\t\t? (\"dashed\" as const)\n\t\t\t\t\t\t\t\t\t: (\"line\" as const),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]\n\t\t\t\t\t: [];\n\t\t\treturn { nodes: [...lines, ...dots], points, legend };\n\t\t},\n\t};\n}\n\n/** A line whose value runs up the y axis, over x positions: a time series. */\nexport function lineY<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: LineOptions<TDatum> = {},\n): ChartMark {\n\treturn lineMark(\"lineY\", data, options);\n}\n\n/** A line whose value runs along x, over y positions. */\nexport function lineX<TDatum>(\n\tdata: ReadonlyArray<TDatum>,\n\toptions: LineOptions<TDatum> = {},\n): ChartMark {\n\treturn lineMark(\"lineX\", data, options);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polar.d.ts","sourceRoot":"","sources":["../../../src/core/marks/polar.ts"],"names":[],"mappings":"AAOA,OAAO,EACN,KAAK,gBAAgB,EAKrB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"polar.d.ts","sourceRoot":"","sources":["../../../src/core/marks/polar.ts"],"names":[],"mappings":"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"}
|
package/dist/core/marks/polar.js
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
seriesResolver,
|
|
12
12
|
tips
|
|
13
13
|
} from "./shared.js";
|
|
14
|
+
import { ARC_MOTION } from "../motion/arc-motion.js";
|
|
15
|
+
import { POINTS_MOTION } from "../motion/points-motion.js";
|
|
14
16
|
import {
|
|
15
17
|
arcPath,
|
|
16
18
|
polarToCartesian,
|
|
@@ -111,6 +113,9 @@ function arc(data, options) {
|
|
|
111
113
|
series: series.key,
|
|
112
114
|
role: "mark",
|
|
113
115
|
d: arcPath(shape),
|
|
116
|
+
geometry: { kind: "arc", ...shape },
|
|
117
|
+
motion: ARC_MOTION,
|
|
118
|
+
enter: options.enter ?? "grow",
|
|
114
119
|
paint: paint({
|
|
115
120
|
fill: series.color,
|
|
116
121
|
stroke: options.stroke ?? context.theme.background,
|
|
@@ -212,6 +217,9 @@ function radialBar(data, options) {
|
|
|
212
217
|
series: series.key,
|
|
213
218
|
role: "mark",
|
|
214
219
|
d: arcPath(shape),
|
|
220
|
+
geometry: { kind: "arc", ...shape },
|
|
221
|
+
motion: ARC_MOTION,
|
|
222
|
+
enter: options.enter ?? "grow",
|
|
215
223
|
paint: paint({ fill: series.color, opacity: options.opacity })
|
|
216
224
|
});
|
|
217
225
|
if (!tips(options.tip, data[index], index)) {
|
|
@@ -395,16 +403,25 @@ function radar(data, options) {
|
|
|
395
403
|
}
|
|
396
404
|
}
|
|
397
405
|
for (const [key, polygon] of polygons) {
|
|
406
|
+
const geometry = {
|
|
407
|
+
kind: "points",
|
|
408
|
+
shape: "polygon",
|
|
409
|
+
runs: [
|
|
410
|
+
polygon.vertices.map((vertex, spoke) => ({
|
|
411
|
+
key: categoryKey(axes[spoke]),
|
|
412
|
+
...vertex ?? { x: frame.cx, y: frame.cy }
|
|
413
|
+
}))
|
|
414
|
+
]
|
|
415
|
+
};
|
|
398
416
|
nodes.push({
|
|
399
417
|
kind: "path",
|
|
400
418
|
key: `${id}:shape:${key}`,
|
|
401
419
|
series: key,
|
|
402
420
|
role: "mark",
|
|
403
|
-
d: polygonPath(
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
),
|
|
421
|
+
d: polygonPath(geometry.runs[0]),
|
|
422
|
+
geometry,
|
|
423
|
+
motion: POINTS_MOTION,
|
|
424
|
+
enter: options.enter,
|
|
408
425
|
paint: paint({
|
|
409
426
|
fill: polygon.color,
|
|
410
427
|
fillOpacity: options.fillOpacity ?? 0.2,
|