UNPKG

@tanstack/charts

Version:

A chart grammar for TypeScript and JavaScript. Marks consume your data directly, channels describe visual encodings, and the engine compiles them into a renderer-neutral keyed scene. TanStack's compact scales cover common numeric and categorical mappings.

77 lines (76 loc) 2.73 kB
import { arc as createArc } from "d3-shape"; import { isFiniteNumber, isNonnegativeFiniteNumber } from "./mark.js"; const tau = Math.PI * 2; let polarSectorArc; function resolvePolarSector(sector) { if (!isFiniteNumber(sector.startAngle) || !isFiniteNumber(sector.endAngle) || !isNonnegativeFiniteNumber(sector.innerRadius) || !isNonnegativeFiniteNumber(sector.outerRadius) || !isNonnegativeFiniteNumber(sector.cornerRadius)) { return void 0; } const generator = polarSectorArc ??= createArc().startAngle((value) => value.startAngle).endAngle((value) => value.endAngle).innerRadius((value) => value.innerRadius).outerRadius((value) => value.outerRadius).cornerRadius((value) => value.cornerRadius); const path = generator(sector); if (typeof path !== "string" || !path) return void 0; return { path, points: tracePolarArcBoundary(generator, sector, 0, [sector]) }; } function tracePolarArcBoundary(generator, datum, index, data) { const points = []; const append = (x, y) => { if (!isFiniteNumber(x) || !isFiniteNumber(y)) return; const previous = points.at(-1); if (previous && Math.abs(previous[0] - x) <= 1e-9 && Math.abs(previous[1] - y) <= 1e-9) { return; } points.push([x, y]); }; const context = { moveTo: append, lineTo: append, arc(centerX, centerY, radius, startAngle, endAngle, counterclockwise = false) { const sweep = canvasArcSweep(startAngle, endAngle, counterclockwise); if (!isFiniteNumber(sweep)) return; if (sweep === 0) { append( centerX + radius * Math.cos(startAngle), centerY + radius * Math.sin(startAngle) ); return; } const steps = Math.max(1, Math.ceil(Math.abs(sweep) / (Math.PI / 24))); for (let index2 = 0; index2 <= steps; index2 += 1) { const angle = startAngle + sweep * index2 / steps; append( centerX + radius * Math.cos(angle), centerY + radius * Math.sin(angle) ); } }, closePath() { } }; const previousContext = generator.context(); generator.context(context); try { generator(datum, index, data); } finally { generator.context(previousContext); } return points; } function canvasArcSweep(startAngle, endAngle, counterclockwise) { const difference = endAngle - startAngle; if (!isFiniteNumber(difference)) return Number.NaN; if (counterclockwise) { if (difference <= -tau) return -tau; const sweep2 = difference % tau; return sweep2 > 0 ? sweep2 - tau : sweep2; } if (difference >= tau) return tau; const sweep = difference % tau; return sweep < 0 ? sweep + tau : sweep; } export { resolvePolarSector, tracePolarArcBoundary };