@mui/x-charts
Version:
The community edition of MUI X Charts components.
136 lines (134 loc) • 5.89 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.computeAxisValue = computeAxisValue;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _defaultValueFormatters = require("../../../defaultValueFormatters");
var _axis = require("../../../../models/axis");
var _colorScale = require("../../../colorScale");
var _ticks = require("../../../ticks");
var _getScale = require("../../../getScale");
var _dateHelpers = require("../../../dateHelpers");
var _getAxisTriggerTooltip = require("./getAxisTriggerTooltip");
var _scaleGuards = require("../../../scaleGuards");
function getRange(drawingArea, axisDirection,
// | 'rotation' | 'radius',
reverse) {
const range = axisDirection === 'x' ? [drawingArea.left, drawingArea.left + drawingArea.width] : [drawingArea.top + drawingArea.height, drawingArea.top];
return reverse ? [range[1], range[0]] : range;
}
function shouldIgnoreGapRatios(scale, categoryGapRatio) {
const step = scale.step();
const paddingPx = step * categoryGapRatio;
/* If the padding is less than 0.1px, we consider it negligible and ignore it.
* This prevents issues where very small gaps cause rendering artifacts or unexpected layouts.
* A threshold of 0.1px is chosen as it's generally below the perceptible limit for most displays.
*/
return paddingPx < 0.1;
}
const DEFAULT_CATEGORY_GAP_RATIO = 0.2;
const DEFAULT_BAR_GAP_RATIO = 0.1;
function computeAxisValue({
scales,
drawingArea,
formattedSeries,
axis: allAxis,
seriesConfig,
axisDirection,
zoomMap,
domains
}) {
if (allAxis === undefined) {
return {
axis: {},
axisIds: []
};
}
const axisIdsTriggeringTooltip = (0, _getAxisTriggerTooltip.getAxisTriggerTooltip)(axisDirection, seriesConfig, formattedSeries, allAxis[0].id);
const completeAxis = {};
allAxis.forEach(eachAxis => {
const axis = eachAxis;
const scale = scales[axis.id];
const zoom = zoomMap?.get(axis.id);
const zoomRange = zoom ? [zoom.start, zoom.end] : [0, 100];
const range = getRange(drawingArea, axisDirection, axis.reverse ?? false);
const rawTickNumber = domains[axis.id].tickNumber;
const triggerTooltip = !axis.ignoreTooltip && axisIdsTriggeringTooltip.has(axis.id);
const tickNumber = (0, _ticks.scaleTickNumberByRange)(rawTickNumber, zoomRange);
const data = axis.data ?? [];
if ((0, _scaleGuards.isOrdinalScale)(scale)) {
// Reverse range because ordinal scales are presented from top to bottom on y-axis
const scaleRange = axisDirection === 'y' ? [range[1], range[0]] : range;
if ((0, _scaleGuards.isBandScale)(scale) && (0, _axis.isBandScaleConfig)(axis)) {
const desiredCategoryGapRatio = axis.categoryGapRatio ?? DEFAULT_CATEGORY_GAP_RATIO;
const ignoreGapRatios = shouldIgnoreGapRatios(scale, desiredCategoryGapRatio);
const categoryGapRatio = ignoreGapRatios ? 0 : desiredCategoryGapRatio;
const barGapRatio = ignoreGapRatios ? 0 : axis.barGapRatio ?? DEFAULT_BAR_GAP_RATIO;
completeAxis[axis.id] = (0, _extends2.default)({
offset: 0,
height: 0,
categoryGapRatio,
barGapRatio,
triggerTooltip
}, axis, {
data,
/* Doing this here is technically wrong, but acceptable in practice.
* In theory, this should be done in the normalized scale selector, but then we'd need that selector to depend
* on the zoom range, which would void its goal (which is to be independent of zoom).
* Since we only ignore gap ratios when they're practically invisible, the small errors caused by this
* discrepancy will hopefully not be noticeable. */
scale: ignoreGapRatios ? scale.copy().padding(0) : scale,
tickNumber,
colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? (0, _colorScale.getOrdinalColorScale)((0, _extends2.default)({
values: axis.data
}, axis.colorMap)) : (0, _colorScale.getColorScale)(axis.colorMap))
});
}
if ((0, _axis.isPointScaleConfig)(axis)) {
completeAxis[axis.id] = (0, _extends2.default)({
offset: 0,
height: 0,
triggerTooltip
}, axis, {
data,
scale,
tickNumber,
colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? (0, _colorScale.getOrdinalColorScale)((0, _extends2.default)({
values: axis.data
}, axis.colorMap)) : (0, _colorScale.getColorScale)(axis.colorMap))
});
}
if ((0, _dateHelpers.isDateData)(axis.data)) {
const dateFormatter = (0, _dateHelpers.createDateFormatter)(axis.data, scaleRange, axis.tickNumber);
completeAxis[axis.id].valueFormatter = axis.valueFormatter ?? dateFormatter;
}
return;
}
if (axis.scaleType === 'band' || axis.scaleType === 'point') {
// Could be merged with the two previous "if conditions" but then TS does not get that `axis.scaleType` can't be `band` or `point`.
return;
}
const continuousAxis = axis;
const scaleType = continuousAxis.scaleType ?? 'linear';
completeAxis[axis.id] = (0, _extends2.default)({
offset: 0,
height: 0,
triggerTooltip
}, continuousAxis, {
data,
scaleType,
scale,
tickNumber,
colorScale: continuousAxis.colorMap && (0, _colorScale.getSequentialColorScale)(continuousAxis.colorMap),
valueFormatter: axis.valueFormatter ?? (0, _defaultValueFormatters.createScalarFormatter)(tickNumber, (0, _getScale.getScale)(scaleType, range.map(v => scale.invert(v)), range))
});
});
return {
axis: completeAxis,
axisIds: allAxis.map(({
id
}) => id)
};
}