UNPKG

@mui/x-charts

Version:

The community edition of MUI X Charts components.

173 lines (171 loc) 6.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useBarPlotData = useBarPlotData; var _getColor = _interopRequireDefault(require("./seriesConfig/getColor")); var _hooks = require("../hooks"); var _checkScaleErrors = require("./checkScaleErrors"); var _useBarSeries = require("../hooks/useBarSeries"); function useBarPlotData(drawingArea, xAxes, yAxes) { const seriesData = (0, _useBarSeries.useBarSeriesContext)() ?? { series: {}, stackingGroups: [], seriesOrder: [] }; const defaultXAxisId = (0, _hooks.useXAxes)().xAxisIds[0]; const defaultYAxisId = (0, _hooks.useYAxes)().yAxisIds[0]; const chartId = (0, _hooks.useChartId)(); const { series, stackingGroups } = seriesData; const masks = {}; const data = stackingGroups.flatMap(({ ids: seriesIds }, groupIndex) => { const xMin = drawingArea.left; const xMax = drawingArea.left + drawingArea.width; const yMin = drawingArea.top; const yMax = drawingArea.top + drawingArea.height; return seriesIds.map(seriesId => { const xAxisId = series[seriesId].xAxisId ?? defaultXAxisId; const yAxisId = series[seriesId].yAxisId ?? defaultYAxisId; const xAxisConfig = xAxes[xAxisId]; const yAxisConfig = yAxes[yAxisId]; const verticalLayout = series[seriesId].layout === 'vertical'; (0, _checkScaleErrors.checkScaleErrors)(verticalLayout, seriesId, series[seriesId], xAxisId, xAxes, yAxisId, yAxes); const baseScaleConfig = verticalLayout ? xAxisConfig : yAxisConfig; const xScale = xAxisConfig.scale; const yScale = yAxisConfig.scale; const colorGetter = (0, _getColor.default)(series[seriesId], xAxes[xAxisId], yAxes[yAxisId]); const bandWidth = baseScaleConfig.scale.bandwidth(); const { barWidth, offset } = getBandSize({ bandWidth, numberOfGroups: stackingGroups.length, gapRatio: baseScaleConfig.barGapRatio }); const barOffset = groupIndex * (barWidth + offset); const { stackedData, data: currentSeriesData, layout, minBarSize } = series[seriesId]; const seriesDataPoints = baseScaleConfig.data.map((baseValue, dataIndex) => { if (currentSeriesData[dataIndex] == null) { return null; } const values = stackedData[dataIndex]; const valueCoordinates = values.map(v => verticalLayout ? yScale(v) : xScale(v)); const minValueCoord = Math.round(Math.min(...valueCoordinates)); const maxValueCoord = Math.round(Math.max(...valueCoordinates)); const stackId = series[seriesId].stack; const { barSize, startCoordinate } = getValueCoordinate(verticalLayout, minValueCoord, maxValueCoord, currentSeriesData[dataIndex], minBarSize); const result = { seriesId, dataIndex, layout, x: verticalLayout ? xScale(baseValue) + barOffset : startCoordinate, y: verticalLayout ? startCoordinate : yScale(baseValue) + barOffset, xOrigin: xScale(0) ?? 0, yOrigin: yScale(0) ?? 0, height: verticalLayout ? barSize : barWidth, width: verticalLayout ? barWidth : barSize, color: colorGetter(dataIndex), value: currentSeriesData[dataIndex], maskId: `${chartId}_${stackId || seriesId}_${groupIndex}_${dataIndex}` }; if (result.x > xMax || result.x + result.width < xMin || result.y > yMax || result.y + result.height < yMin) { return null; } if (!masks[result.maskId]) { masks[result.maskId] = { id: result.maskId, width: 0, height: 0, hasNegative: false, hasPositive: false, layout: result.layout, xOrigin: xScale(0), yOrigin: yScale(0), x: 0, y: 0 }; } const mask = masks[result.maskId]; mask.width = result.layout === 'vertical' ? result.width : mask.width + result.width; mask.height = result.layout === 'vertical' ? mask.height + result.height : result.height; mask.x = Math.min(mask.x === 0 ? Infinity : mask.x, result.x); mask.y = Math.min(mask.y === 0 ? Infinity : mask.y, result.y); mask.hasNegative = mask.hasNegative || (result.value ?? 0) < 0; mask.hasPositive = mask.hasPositive || (result.value ?? 0) > 0; return result; }).filter(rectangle => rectangle !== null); return { seriesId, data: seriesDataPoints }; }); }); return { completedData: data, masksData: Object.values(masks) }; } /** * Solution of the equations * W = barWidth * N + offset * (N-1) * offset / (offset + barWidth) = r * @param bandWidth The width available to place bars. * @param numberOfGroups The number of bars to place in that space. * @param gapRatio The ratio of the gap between bars over the bar width. * @returns The bar width and the offset between bars. */ function getBandSize({ bandWidth: W, numberOfGroups: N, gapRatio: r }) { if (r === 0) { return { barWidth: W / N, offset: 0 }; } const barWidth = W / (N + (N - 1) * r); const offset = r * barWidth; return { barWidth, offset }; } function getValueCoordinate(isVertical, minValueCoord, maxValueCoord, baseValue, minBarSize) { if (baseValue === 0 || baseValue == null) { return { barSize: 0, startCoordinate: minValueCoord }; } const isSizeLessThanMin = maxValueCoord - minValueCoord < minBarSize; const barSize = isSizeLessThanMin ? minBarSize : maxValueCoord - minValueCoord; const isVerticalAndPositive = isVertical && baseValue >= 0; const isHorizontalAndNegative = !isVertical && baseValue < 0; if (isSizeLessThanMin && (isVerticalAndPositive || isHorizontalAndNegative)) { return { barSize, startCoordinate: maxValueCoord - barSize }; } return { barSize, startCoordinate: minValueCoord }; }