UNPKG

shown

Version:

Statically-generated, responsive charts, without the need for client-side Javascript.

65 lines (47 loc) 1.41 kB
import { min, abs, clamp } from "../utils/math.js" const TENSION = 1 / 3 const sign = (v) => (v < 0 ? -1 : 1) const slope = (x0, y0, x1, y1, x2, y2) => { const h0 = x1 - x0 const h1 = x2 - x1 const s0 = (y1 - y0) / (h0 || (h1 < 0 && -0)) const s1 = (y2 - y1) / (h1 || (h0 < 0 && -0)) const p = (s0 * h1 + s1 * h0) / (h0 + h1) return (sign(s0) + sign(s1)) * min(abs(s0), abs(s1), abs(p) / 2) || 0 } const curve = (x0, y0, x1, y1, s0, s1, alpha) => { const ratio = abs((y1 - y0) / (x1 - x0)) const scale = clamp(ratio, 1, 1.5) const delta = (x1 - x0) * alpha * scale return ["C", x0 + delta, y0 + delta * s0, x1 - delta, y1 - delta * s1, x1, y1] } export default (points, alpha = TENSION) => { const m = [] let s0, s1 let p0, p1, p2 for (let i = 0; i < points.length; i++) { p0 = p1 || points[i - 1] p1 = p2 || points[i + 0] p2 = points[i + 1] if (!p0 && !p2) { return m } if (!p0) { p0 = [p1[0] - (p2[0] - p1[0]) / 2, p1[1] - (p2[1] - p1[1]) / 2] } if (!p2) { p2 = [p1[0] + (p1[0] - p0[0]) / 2, p1[1] + (p1[1] - p0[1]) / 2] } const [x0, y0] = p0 const [x1, y1] = p1 const [x2, y2] = p2 s1 = slope(x0, y0, x1, y1, x2, y2) if (i === 0) { m.push("M", x1, y1) } else if (x0 !== x1 || y0 !== y1) { m.push(...curve(x0, y0, x1, y1, s0, s1, alpha)) } s0 = s1 } return m }