UNPKG

victory-native

Version:

A charting library for React Native with a focus on performance and customization.

243 lines (242 loc) 10.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformHorizontalInputData = void 0; const getOffsetFromAngle_1 = require("../../utils/getOffsetFromAngle"); const tickHelpers_1 = require("../../utils/tickHelpers"); const getAxisLabelLayout_1 = require("./getAxisLabelLayout"); const getAxisTitleLayout_1 = require("./getAxisTitleLayout"); const getXAxisTicks_1 = require("./getXAxisTicks"); const getYScaleInputBounds_1 = require("./getYScaleInputBounds"); const makeScale_1 = require("./makeScale"); const transformHorizontalInputData = ({ data: _data, xKey, yKeys, outputWindow, domain, domainPadding, xAxis, yAxes, viewport, labelRotate, axisScales, }) => { const data = [..._data]; const { xAxisScale = "linear" } = axisScales || {}; const isNumericalData = data.every((datum) => typeof datum[xKey] === "number"); if (isNumericalData) { data.sort((a, b) => +a[xKey] - +b[xKey]); } const y = yKeys.reduce((acc, k) => { acc[k] = { i: [], o: [] }; return acc; }, {}); const ix = data.map((datum) => datum[xKey]); const categoryIndexes = ix.map((_, index) => index); const categoryAxisLayouts = yAxes.map((yAxis) => { const ticks = yAxis.tickValues ? (0, tickHelpers_1.downsampleTicks)(yAxis.tickValues, yAxis.tickCount) : (0, tickHelpers_1.downsampleTicks)(categoryIndexes, yAxis.tickCount); const labelLayouts = ticks.map((tick, index) => { const categoryValue = ix[tick]; const labelValue = yAxis.formatYLabel ? yAxis.formatYLabel(categoryValue) : String(categoryValue !== null && categoryValue !== void 0 ? categoryValue : tick); return (0, getAxisLabelLayout_1.getAxisLabelLayout)({ axis: "y", orientation: "horizontal", value: categoryValue, text: String(labelValue), index, font: yAxis.font, labelRenderer: yAxis.labelRenderer, }); }); const maxLabelLayout = (0, getAxisLabelLayout_1.getMaxAxisLabelLayout)(labelLayouts); const titleLayout = (0, getAxisTitleLayout_1.getAxisTitleLayout)({ title: yAxis.title, font: yAxis.font, }); const titleOutset = titleLayout.hasContent ? titleLayout.height + titleLayout.offset : 0; return { ticks, maxLabelLayout, titleOutset, }; }); const valueTickValues = xAxis.tickValues; const valueTickCount = xAxis.tickCount; const tickDomainsX = (0, tickHelpers_1.getDomainFromTicks)(valueTickValues); const valueInputBounds = getHorizontalValueInputBounds({ data, yKeys: yKeys, domain: domain === null || domain === void 0 ? void 0 : domain.x, tickDomain: tickDomainsX, includeZero: !(domain === null || domain === void 0 ? void 0 : domain.x) && !tickDomainsX, }); const rawChartWidth = outputWindow.xMax - outputWindow.xMin; const xTempScale = (0, makeScale_1.makeScale)({ inputBounds: valueInputBounds, outputBounds: [0, rawChartWidth], axisScale: xAxisScale, }); const xTicksForLabelLayout = (0, getXAxisTicks_1.getXAxisTicks)({ isNumericalData: true, ix: [], tickCount: valueTickCount, tickValues: valueTickValues, xScale: xTempScale, }); const xAxisLabelLayouts = xTicksForLabelLayout.map((xTick, index) => { const labelValue = xAxis.formatXLabel ? xAxis.formatXLabel(xTick) : String(xTick); return (0, getAxisLabelLayout_1.getAxisLabelLayout)({ axis: "x", orientation: "horizontal", value: xTick, text: String(labelValue), index, font: xAxis.font, labelRenderer: xAxis.labelRenderer, }); }); const maxXLabelLayout = (0, getAxisLabelLayout_1.getMaxAxisLabelLayout)(xAxisLabelLayouts); const xAxisTitleLayout = (0, getAxisTitleLayout_1.getAxisTitleLayout)({ title: xAxis.title, font: xAxis.font, }); const xAxisTitleOutset = xAxisTitleLayout.hasContent ? xAxisTitleLayout.height + xAxisTitleLayout.offset : 0; const adjustedOutputWindow = Object.assign({}, outputWindow); if (labelRotate && xAxis.labelPosition === "outset") { const rotateOffset = Math.abs(maxXLabelLayout.width * (0, getOffsetFromAngle_1.getOffsetFromAngle)(labelRotate)); if (xAxis.axisSide === "bottom") { adjustedOutputWindow.yMax -= rotateOffset; } else if (xAxis.axisSide === "top") { adjustedOutputWindow.yMin += rotateOffset; } } const xRange = (() => { let xMinAdjustment = 0; let xMaxAdjustment = 0; yAxes.forEach((axis, index) => { var _a, _b, _c, _d; const labelWidth = (_b = (_a = categoryAxisLayouts[index]) === null || _a === void 0 ? void 0 : _a.maxLabelLayout.width) !== null && _b !== void 0 ? _b : 0; const titleOutset = (_d = (_c = categoryAxisLayouts[index]) === null || _c === void 0 ? void 0 : _c.titleOutset) !== null && _d !== void 0 ? _d : 0; if (axis.axisSide === "left") { xMinAdjustment += titleOutset; if (axis.labelPosition === "outset" && axis.tickCount > 0 && labelWidth > 0) { xMinAdjustment += labelWidth + axis.labelOffset; } } if (axis.axisSide === "right") { xMaxAdjustment -= titleOutset; if (axis.labelPosition === "outset" && axis.tickCount > 0 && labelWidth > 0) { xMaxAdjustment -= labelWidth + axis.labelOffset; } } }); return [ adjustedOutputWindow.xMin + xMinAdjustment, adjustedOutputWindow.xMax + xMaxAdjustment, ]; })(); const categoryRange = (() => { var _a; const xLabelOffset = (_a = xAxis.labelOffset) !== null && _a !== void 0 ? _a : 0; const xLabelOutset = valueTickCount > 0 && maxXLabelLayout.width > 0 ? maxXLabelLayout.height + xLabelOffset * 2 : 0; const xAxisOutset = xAxisTitleOutset + (xAxis.labelPosition === "outset" ? xLabelOutset : 0); if (xAxis.axisSide === "bottom") { return [ adjustedOutputWindow.yMin, adjustedOutputWindow.yMax - xAxisOutset, ]; } if (xAxis.axisSide === "top") { return [ adjustedOutputWindow.yMin + xAxisOutset, adjustedOutputWindow.yMax, ]; } return [adjustedOutputWindow.yMin, adjustedOutputWindow.yMax]; })(); const xScale = (0, makeScale_1.makeScale)({ inputBounds: valueInputBounds, outputBounds: xRange, viewport: viewport === null || viewport === void 0 ? void 0 : viewport.x, padStart: typeof domainPadding === "number" ? domainPadding : domainPadding === null || domainPadding === void 0 ? void 0 : domainPadding.left, padEnd: typeof domainPadding === "number" ? domainPadding : domainPadding === null || domainPadding === void 0 ? void 0 : domainPadding.right, axisScale: xAxisScale, }); const categoryInputBounds = getCategoryInputBounds(categoryIndexes); const yScale = (0, makeScale_1.makeScale)({ inputBounds: categoryInputBounds, outputBounds: categoryRange, viewport: viewport === null || viewport === void 0 ? void 0 : viewport.y, padStart: typeof domainPadding === "number" ? domainPadding : domainPadding === null || domainPadding === void 0 ? void 0 : domainPadding.top, padEnd: typeof domainPadding === "number" ? domainPadding : domainPadding === null || domainPadding === void 0 ? void 0 : domainPadding.bottom, }); const yData = yKeys.reduce((acc, key) => { acc[key] = { i: data.map((datum) => datum[key]), o: data.map((datum) => typeof datum[key] === "number" ? xScale(datum[key]) : datum[key]), }; return acc; }, {}); yKeys.forEach((yKey) => { y[yKey].i = data.map((datum) => datum[yKey]); y[yKey].o = data.map((datum) => (typeof datum[yKey] === "number" ? xScale(datum[yKey]) : datum[yKey])); }); const ox = categoryIndexes.map((index) => yScale(index)); const xTicksNormalized = (0, getXAxisTicks_1.getXAxisTicks)({ isNumericalData: true, ix: [], tickCount: valueTickCount, tickValues: valueTickValues, xScale, }); const yAxesTransformed = yAxes.map((_, index) => { var _a, _b, _c, _d; return ({ yScale, yTicksNormalized: (_b = (_a = categoryAxisLayouts[index]) === null || _a === void 0 ? void 0 : _a.ticks) !== null && _b !== void 0 ? _b : [], yData, maxYLabel: (_d = (_c = categoryAxisLayouts[index]) === null || _c === void 0 ? void 0 : _c.maxLabelLayout.width) !== null && _d !== void 0 ? _d : 0, }); }); return { ix, y, isNumericalData, ox, xScale, xTicksNormalized, yAxes: [yAxesTransformed[0], ...yAxesTransformed.slice(1)], }; }; exports.transformHorizontalInputData = transformHorizontalInputData; const getCategoryInputBounds = (indexes) => { var _a, _b; const first = (_a = indexes.at(0)) !== null && _a !== void 0 ? _a : 0; const last = (_b = indexes.at(-1)) !== null && _b !== void 0 ? _b : 0; return first === last ? [first - 1, last + 1] : [first, last]; }; const getHorizontalValueInputBounds = ({ data, yKeys, domain, tickDomain, includeZero, }) => { const { yMin, yMax } = (0, getYScaleInputBounds_1.getYScaleInputBounds)({ data, yKeys, domain, tickDomain, }); if (!Number.isFinite(yMin) || !Number.isFinite(yMax)) { return [-1, 1]; } const valueMin = includeZero ? Math.min(0, yMin) : yMin; const valueMax = includeZero ? Math.max(0, yMax) : yMax; return valueMin === valueMax ? [valueMin - 1, valueMax + 1] : [valueMin, valueMax]; };