UNPKG

react-native-graph-plus

Version:

📈 Beautiful, high-performance Graphs and Charts for React Native +

167 lines (134 loc) • 6.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createGraphPath = createGraphPath; exports.createGraphPathWithGradient = createGraphPathWithGradient; exports.getGraphPathRange = getGraphPathRange; exports.getYPositionInRange = exports.getYInRange = exports.getXPositionInRange = exports.getXInRange = exports.getPointsInRange = void 0; var _reactNativeSkia = require("@shopify/react-native-skia"); const PIXEL_RATIO = 2; function getGraphPathRange(points, range) { var _ref, _range$x$min, _range$x, _points$, _ref2, _range$x$max, _range$x2, _points, _range$y$min, _range$y, _range$y$max, _range$y2; const minValueX = (_ref = (_range$x$min = range === null || range === void 0 ? void 0 : (_range$x = range.x) === null || _range$x === void 0 ? void 0 : _range$x.min) !== null && _range$x$min !== void 0 ? _range$x$min : (_points$ = points[0]) === null || _points$ === void 0 ? void 0 : _points$.date) !== null && _ref !== void 0 ? _ref : new Date(); const maxValueX = (_ref2 = (_range$x$max = range === null || range === void 0 ? void 0 : (_range$x2 = range.x) === null || _range$x2 === void 0 ? void 0 : _range$x2.max) !== null && _range$x$max !== void 0 ? _range$x$max : (_points = points[points.length - 1]) === null || _points === void 0 ? void 0 : _points.date) !== null && _ref2 !== void 0 ? _ref2 : new Date(); const minValueY = (_range$y$min = range === null || range === void 0 ? void 0 : (_range$y = range.y) === null || _range$y === void 0 ? void 0 : _range$y.min) !== null && _range$y$min !== void 0 ? _range$y$min : points.reduce((prev, curr) => curr.value < prev ? curr.value : prev, Number.MAX_SAFE_INTEGER); const maxValueY = (_range$y$max = range === null || range === void 0 ? void 0 : (_range$y2 = range.y) === null || _range$y2 === void 0 ? void 0 : _range$y2.max) !== null && _range$y$max !== void 0 ? _range$y$max : points.reduce((prev, curr) => curr.value > prev ? curr.value : prev, Number.MIN_SAFE_INTEGER); return { x: { min: minValueX, max: maxValueX }, y: { min: minValueY, max: maxValueY } }; } const getXPositionInRange = (date, xRange) => { const diff = xRange.max.getTime() - xRange.min.getTime(); const x = date.getTime(); return (x - xRange.min.getTime()) / diff; }; exports.getXPositionInRange = getXPositionInRange; const getXInRange = (width, date, xRange) => { return Math.floor(width * getXPositionInRange(date, xRange)); }; exports.getXInRange = getXInRange; const getYPositionInRange = (value, yRange) => { const diff = yRange.max - yRange.min; const y = value; return (y - yRange.min) / diff; }; exports.getYPositionInRange = getYPositionInRange; const getYInRange = (height, value, yRange) => { return Math.floor(height * getYPositionInRange(value, yRange)); }; exports.getYInRange = getYInRange; const getPointsInRange = (allPoints, range) => { return allPoints.filter(point => { const portionFactorX = getXPositionInRange(point.date, range.x); return portionFactorX <= 1 && portionFactorX >= 0; }); }; exports.getPointsInRange = getPointsInRange; function createGraphPathBase(_ref3) { let { pointsInRange: graphData, range, horizontalPadding, verticalPadding, canvasHeight: height, canvasWidth: width, shouldFillGradient } = _ref3; const path = _reactNativeSkia.Skia.Path.Make(); // Canvas width substracted by the horizontal padding => Actual drawing width const drawingWidth = width - 2 * horizontalPadding; // Canvas height substracted by the vertical padding => Actual drawing height const drawingHeight = height - 2 * verticalPadding; if (graphData[0] == null) return path; const points = []; const startX = getXInRange(drawingWidth, graphData[0].date, range.x) + horizontalPadding; const endX = getXInRange(drawingWidth, graphData[graphData.length - 1].date, range.x) + horizontalPadding; const getGraphDataIndex = pixel => Math.round((pixel - startX) / (endX - startX) * (graphData.length - 1)); const getNextPixelValue = pixel => { if (pixel === endX || pixel + PIXEL_RATIO < endX) return pixel + PIXEL_RATIO; return endX; }; for (let pixel = startX; startX <= pixel && pixel <= endX; pixel = getNextPixelValue(pixel)) { const index = getGraphDataIndex(pixel); // Draw first point only on the very first pixel if (index === 0 && pixel !== startX) continue; // Draw last point only on the very last pixel if (index === graphData.length - 1 && pixel !== endX) continue; if (index !== 0 && index !== graphData.length - 1) { // Only draw point, when the point is exact const exactPointX = getXInRange(drawingWidth, graphData[index].date, range.x) + horizontalPadding; const isExactPointInsidePixelRatio = Array(PIXEL_RATIO).fill(0).some((_value, additionalPixel) => { return pixel + additionalPixel === exactPointX; }); if (!isExactPointInsidePixelRatio) continue; } const value = graphData[index].value; const y = drawingHeight - getYInRange(drawingHeight, value, range.y) + verticalPadding; points.push({ x: pixel, y: y }); } for (let i = 0; i < points.length; i++) { const point = points[i]; // first point needs to start the path if (i === 0) path.moveTo(point.x, point.y); const prev = points[i - 1]; const prevPrev = points[i - 2]; if (prev == null) continue; const p0 = prevPrev !== null && prevPrev !== void 0 ? prevPrev : prev; const p1 = prev; const cp1x = (2 * p0.x + p1.x) / 3; const cp1y = (2 * p0.y + p1.y) / 3; const cp2x = (p0.x + 2 * p1.x) / 3; const cp2y = (p0.y + 2 * p1.y) / 3; const cp3x = (p0.x + 4 * p1.x + point.x) / 6; const cp3y = (p0.y + 4 * p1.y + point.y) / 6; path.cubicTo(cp1x, cp1y, cp2x, cp2y, cp3x, cp3y); if (i === points.length - 1) { path.cubicTo(point.x, point.y, point.x, point.y, point.x, point.y); } } if (!shouldFillGradient) return path; const gradientPath = path.copy(); gradientPath.lineTo(endX, height + verticalPadding); gradientPath.lineTo(0 + horizontalPadding, height + verticalPadding); return { path: path, gradientPath: gradientPath }; } function createGraphPath(props) { return createGraphPathBase({ ...props, shouldFillGradient: false }); } function createGraphPathWithGradient(props) { return createGraphPathBase({ ...props, shouldFillGradient: true }); } //# sourceMappingURL=CreateGraphPath.js.map