UNPKG

ag-charts-community

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

67 lines 2.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function circleRectOverlap(cx, cy, r, x, y, w, h) { // Find closest horizontal and vertical edges. let edgeX = cx < x ? x : cx > x + w ? x + w : cx; let edgeY = cy < y ? y : cy > y + h ? y + h : cy; // Find distance to closest edges. const dx = cx - edgeX; const dy = cy - edgeY; const d = Math.sqrt((dx * dx) + (dy * dy)); return d <= r; } function rectRectOverlap(x1, y1, w1, h1, x2, y2, w2, h2) { const xOverlap = (x1 + w1) > x2 && x1 < (x2 + w2); const yOverlap = (y1 + h1) > y2 && y1 < (y2 + h2); return xOverlap && yOverlap; } function rectContainsRect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h) { return (r2x + r2w) < (r1x + r1w) && (r2x) > (r1x) && (r2y) > (r1y) && (r2y + r2h) < (r1y + r1h); } /** * @param data Points and labels for one or more series. The order of series determines label placement precedence. * @param bounds Bounds to fit the labels into. If a label can't be fully contained, it doesn't fit. * @returns Placed labels for the given series (in the given order). */ function placeLabels(data, bounds, padding = 5) { const result = []; data = data.map(d => d.slice().sort((a, b) => b.size - a.size)); for (let j = 0; j < data.length; j++) { const labels = result[j] = []; const datum = data[j]; if (!(datum && datum.length && datum[0].label)) { continue; } for (let i = 0, ln = datum.length; i < ln; i++) { const d = datum[i]; const l = d.label; const r = d.size * 0.5; const x = d.point.x - l.width * 0.5; const y = d.point.y - r - l.height - padding; const { width, height } = l; const withinBounds = !bounds || rectContainsRect(bounds.x, bounds.y, bounds.width, bounds.height, x, y, width, height); if (!withinBounds) { continue; } const overlapPoints = data.some(datum => datum.some(d => circleRectOverlap(d.point.x, d.point.y, d.size * 0.5, x, y, width, height))); if (overlapPoints) { continue; } const overlapLabels = result.some(labels => labels.some(l => rectRectOverlap(l.x, l.y, l.width, l.height, x, y, width, height))); if (overlapLabels) { continue; } labels.push({ index: i, text: l.text, x, y, width, height }); } } return result; } exports.placeLabels = placeLabels; //# sourceMappingURL=labelPlacement.js.map