UNPKG

react-native-chart-kit

Version:

Beautiful React Native charts for dashboards, reports, and data-rich mobile apps.

99 lines (98 loc) 3.39 kB
import { cubicCommand, horizontalCommand, pointCommand, verticalCommand } from "./path"; import { getDecimatedLinePathSegments, splitLinePathSegments } from "./lineDecimation"; export const splitDefinedSegments = (points, connectNulls = false) => splitLinePathSegments(points, connectNulls); const buildLinearSegmentPath = (points) => { return points .map((point, index) => pointCommand(index === 0 ? "M" : "L", point.x, point.y)) .join(" "); }; const buildStepSegmentPath = (points) => { if (points.length === 0) { return ""; } const first = points[0]; if (!first) { return ""; } const rest = points.slice(1); let path = pointCommand("M", first.x, first.y); let previous = first; rest.forEach((point) => { const midpoint = previous.x + (point.x - previous.x) / 2; path = [ path, horizontalCommand(midpoint), verticalCommand(point.y), horizontalCommand(point.x) ].join(" "); previous = point; }); return path; }; const isStrictlyIncreasingX = (points) => { return points.every((point, index) => { return index === 0 || point.x > points[index - 1].x; }); }; const buildMonotoneSegmentPath = (points) => { if (points.length < 3 || !isStrictlyIncreasingX(points)) { return buildLinearSegmentPath(points); } const slopes = points.slice(0, -1).map((point, index) => { const next = points[index + 1]; return (next.y - point.y) / (next.x - point.x); }); const tangents = points.map((_, index) => { if (index === 0) { return slopes[0]; } if (index === points.length - 1) { return slopes[slopes.length - 1]; } const previousSlope = slopes[index - 1]; const nextSlope = slopes[index]; if (previousSlope * nextSlope <= 0) { return 0; } const sign = Math.sign(previousSlope); return (sign * Math.min(Math.abs(previousSlope), Math.abs(nextSlope), Math.abs((previousSlope + nextSlope) / 2))); }); let path = pointCommand("M", points[0].x, points[0].y); for (let index = 0; index < points.length - 1; index++) { const point = points[index]; const next = points[index + 1]; const deltaX = next.x - point.x; path = [ path, cubicCommand(point.x + deltaX / 3, point.y + (tangents[index] * deltaX) / 3, next.x - deltaX / 3, next.y - (tangents[index + 1] * deltaX) / 3, next.x, next.y) ].join(" "); } return path; }; export const buildLineSegmentPath = (points, curve = "linear") => { if (points.length === 0) { return ""; } if (curve === "step") { return buildStepSegmentPath(points); } if (curve === "monotone") { return buildMonotoneSegmentPath(points); } return buildLinearSegmentPath(points); }; export const buildLinePath = ({ points, curve = "linear", connectNulls = false, decimation }) => { const segments = getDecimatedLinePathSegments({ points, connectNulls, decimation }).map((segment) => ({ points: segment, path: buildLineSegmentPath(segment, curve) })); return { segments, path: segments.map((segment) => segment.path).join(" ") }; };