@mui/x-charts
Version:
The community edition of MUI X Charts components.
173 lines (171 loc) • 6.2 kB
JavaScript
"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
};
}