UNPKG

@thi.ng/viz

Version:

Declarative, functional & multi-format data visualization toolkit based around @thi.ng/hiccup

152 lines (151 loc) 3.26 kB
import { eqDelta } from "@thi.ng/math/eqdelta"; import { comp } from "@thi.ng/transducers/comp"; import { iterator } from "@thi.ng/transducers/iterator"; import { filter } from "@thi.ng/transducers/filter"; import { mapcat } from "@thi.ng/transducers/mapcat"; const __gridAxis = ({ domain, major, minor }, majorTickFn, minorTickFn) => { const majorTicks = [...major.ticks(domain)]; return [ ["path", {}, [...mapcat(majorTickFn, majorTicks)]], [ "path", {}, [ ...iterator( comp( filter( (x) => majorTicks.find((y) => eqDelta(x, y)) === void 0 ), mapcat(minorTickFn) ), minor.ticks(domain) ) ] ] ]; }; const NONE = () => null; const __gridCartesian = ({ xaxis, yaxis, grid }) => { grid = { attribs: { stroke: [0, 0, 0, 0.2], "stroke-dasharray": "1 1" }, xmajor: true, xminor: true, ymajor: true, yminor: true, ...grid }; const [x1, x2] = xaxis.range; const [y1, y2] = yaxis.range; const lineX = (x) => [ ["M", [xaxis.scale(x), y1]], ["V", y2] ]; const lineY = (x) => [ ["M", [x1, yaxis.scale(x)]], ["H", x2] ]; return [ "g", grid.attribs, ...__gridAxis( xaxis, grid.xmajor ? lineX : NONE, grid.xminor ? lineX : NONE ), ...__gridAxis( yaxis, grid.ymajor ? lineY : NONE, grid.yminor ? lineY : NONE ) ]; }; const __axisCommon = (spec, axis, majorTickFn, minorTickFn, labelFn) => { const majorTicks = [...spec.major.ticks(spec.domain)]; return [ "g", spec.attribs, axis, ...__gridAxis(spec, majorTickFn, minorTickFn), [ "g", { stroke: "none", ...spec.labelAttribs }, ...majorTicks.map(labelFn) ] ]; }; const cartesianAxisX = (spec) => { const { pos, scale, format, label, labelOffset: [lx, ly], range: [r1, r2] } = spec; const tick = (dy) => (x) => [ ["M", [scale(x), pos]], ["v", dy] ]; return __axisCommon( spec, [ "path", {}, [ ["M", [r1, pos]], ["L", [r2, pos]] ] ], tick(spec.major.size), tick(spec.minor.size), (x) => label([scale(x) + lx, pos + ly], format(x)) ); }; const cartesianAxisY = (spec) => { const { pos, scale, format, label, labelOffset: [lx, ly], range: [r1, r2] } = spec; const tick = (dx) => (y) => [ ["M", [pos, scale(y)]], ["h", dx] ]; return __axisCommon( spec, [ "path", {}, [ ["M", [pos, r1]], ["L", [pos, r2]] ] ], tick(-spec.major.size), tick(-spec.minor.size), (y) => label([pos + lx, scale(y) + ly], format(y)) ); }; const DEFAULT_ATTRIBS = { "font-family": "Arial, Helvetica, sans-serif", "font-size": "10px" }; const plotCartesian = (spec) => { const { xaxis, yaxis, plots } = spec; return [ "g", { ...DEFAULT_ATTRIBS, ...spec.attribs }, spec.grid ? __gridCartesian(spec) : null, ...plots.map((fn) => fn(spec)), xaxis.visible ? cartesianAxisX(xaxis) : null, yaxis.visible ? cartesianAxisY(yaxis) : null ]; }; export { cartesianAxisX, cartesianAxisY, plotCartesian };