UNPKG

react-native-chart-kit

Version:

Beautiful React Native charts for dashboards, reports, and data-rich mobile apps.

91 lines (90 loc) 3.04 kB
const boxesOverlap = (left, right, gap) => { return left.x + left.width + gap > right.x; }; const hasOverlap = (labels, indexes, gap) => { for (let i = 1; i < indexes.length; i++) { const previousIndex = indexes[i - 1]; const currentIndex = indexes[i]; if (previousIndex === undefined || currentIndex === undefined) { continue; } const previous = labels[previousIndex]; const current = labels[currentIndex]; if (previous && current && boxesOverlap(previous, current, gap)) { return true; } } return false; }; const visibleIndexesForInterval = (count, interval) => { return Array.from({ length: count }, (_, index) => index).filter((index) => { return index === 0 || index === count - 1 || index % interval === 0; }); }; export const solveLabelCollision = ({ labels, availableWidth, allowRotate = true, allowStagger = true, minGap = 4, maxRotation = 45 }) => { if (labels.length === 0) { return { strategy: "show", visibleIndexes: [], interval: 1, rotation: 0, rows: 1 }; } const allIndexes = visibleIndexesForInterval(labels.length, 1); if (!hasOverlap(labels, allIndexes, minGap)) { return { strategy: "show", visibleIndexes: allIndexes, interval: 1, rotation: 0, rows: 1 }; } if (allowStagger) { const rowWidth = labels.reduce((max, label) => Math.max(max, label.width), 0); const approximateSlot = availableWidth / Math.max(1, labels.length); if (rowWidth + minGap <= approximateSlot * 2) { return { strategy: "stagger", visibleIndexes: allIndexes, interval: 1, rotation: 0, rows: 2 }; } } if (allowRotate) { const widest = labels.reduce((max, label) => Math.max(max, label.width), 0); const rotatedWidth = widest * Math.cos((Math.abs(maxRotation) * Math.PI) / 180); const approximateSlot = availableWidth / Math.max(1, labels.length); if (rotatedWidth + minGap <= approximateSlot) { return { strategy: "rotate", visibleIndexes: allIndexes, interval: 1, rotation: maxRotation, rows: 1 }; } } for (let interval = 2; interval <= labels.length; interval++) { const visibleIndexes = visibleIndexesForInterval(labels.length, interval); if (!hasOverlap(labels, visibleIndexes, minGap)) { return { strategy: "skip", visibleIndexes, interval, rotation: 0, rows: 1 }; } } return { strategy: "hide", visibleIndexes: [], interval: labels.length, rotation: 0, rows: 0 }; };