react-native-chart-kit
Version:
Beautiful React Native charts for dashboards, reports, and data-rich mobile apps.
88 lines (87 loc) • 3.22 kB
JavaScript
export const lineChartTooltipLineHeight = 18;
export const lineChartTooltipLabelLineHeight = 16;
const clamp = (value, min, max) => {
if (max < min) {
return min;
}
return Math.min(Math.max(value, min), max);
};
export const easeLineChartTooltipPosition = (progress) => {
const clampedProgress = clamp(progress, 0, 1);
return 1 - Math.pow(1 - clampedProgress, 3);
};
export const interpolateLineChartTooltipPosition = ({ from, progress, to }) => {
const easedProgress = easeLineChartTooltipPosition(progress);
return {
x: from.x + (to.x - from.x) * easedProgress,
y: from.y + (to.y - from.y) * easedProgress
};
};
const getTooltipX = ({ chartWidth, edgePadding, anchorX, leftInset = edgePadding, width }) => clamp(anchorX - width / 2, leftInset, chartWidth - width - edgePadding);
const getTooltipY = ({ anchorY, chartHeight, config, height, plotY }) => {
const minY = config.edgePadding;
const maxY = chartHeight - height - config.edgePadding;
const aboveY = anchorY - height - config.offset;
const belowY = anchorY + config.offset;
if (config.placement === "above") {
return clamp(aboveY, minY, maxY);
}
if (config.placement === "below") {
return clamp(belowY, minY, maxY);
}
return aboveY >= plotY ? aboveY : clamp(belowY, minY, maxY);
};
export const clampLineChartTooltipToViewport = (tooltip, { leftInset = 4, scrollOffset, viewportWidth }) => ({
...tooltip,
x: clamp(tooltip.x, scrollOffset + leftInset, scrollOffset + viewportWidth - tooltip.width - tooltip.config.edgePadding)
});
export const getLineChartTooltipModel = ({ chartHeight, chartWidth, config, measureText, plotX, plotY, selection, theme }) => {
if (!config.visible || selection.series.length === 0) {
return undefined;
}
const series = config.shared
? selection.series
: selection.series.slice(0, 1);
const labelWidth = measureText(selection.xLabel, {
fontSize: config.labelFontSize
}).width;
const seriesTextWidths = series.map((item) => measureText(`${item.label}: ${item.formattedValue}`, {
fontSize: config.fontSize
}).width);
const markerWidth = 12;
const contentWidth = Math.max(labelWidth, ...seriesTextWidths) + markerWidth;
const width = config.width ?? contentWidth + config.padding * 2;
const height = config.padding * 2 +
lineChartTooltipLabelLineHeight +
series.length * lineChartTooltipLineHeight;
const anchor = config.anchor === "pointer" && selection.pointer
? selection.pointer
: selection;
const x = getTooltipX({
chartWidth,
edgePadding: config.edgePadding,
leftInset: plotX === undefined
? config.edgePadding
: Math.max(config.edgePadding, plotX + config.edgePadding),
anchorX: anchor.x,
width
});
const y = getTooltipY({
anchorY: anchor.y,
chartHeight,
config,
height,
plotY
});
return {
index: selection.index,
x,
y,
width,
height,
xLabel: selection.xLabel,
series,
config,
theme
};
};