UNPKG

highcharts

Version:
162 lines (161 loc) 5.34 kB
/* * * * Imports * * */ import { addEvent, correctFloat, defined, pick } from '../../Shared/Utilities.js'; /* * * * Functions * * */ /** @internal */ function chartGetHoverPane(eventArgs) { const chart = this; let hoverPane; if (eventArgs) { chart.pane.forEach((pane) => { const x = eventArgs.chartX - chart.plotLeft, y = eventArgs.chartY - chart.plotTop; if (isInsidePane(x, y, pane.center)) { hoverPane = pane; } }); } return hoverPane; } /** * Adjusts the clipBox based on the position of panes. * @internal */ function onSetClip({ clipBox }) { if (!this.xAxis || !this.yAxis || (!this.chart.angular && !this.chart.polar)) { return; } const { plotWidth, plotHeight } = this.chart, smallestSize = Math.min(plotWidth, plotHeight), xPane = this.xAxis.pane, yPane = this.yAxis.pane; if (xPane && xPane.axis) { clipBox.x += xPane.center[0] - (xPane.center[2] / smallestSize) * plotWidth / 2; } if (yPane && yPane.axis) { clipBox.y += yPane.center[1] - (yPane.center[2] / smallestSize) * plotHeight / 2; } } /** @internal */ function compose(ChartClass, PointerClass, SeriesClass) { const chartProto = ChartClass.prototype; if (!chartProto.getHoverPane) { chartProto.collectionsWithUpdate.push('pane'); chartProto.getHoverPane = chartGetHoverPane; addEvent(ChartClass, 'afterIsInsidePlot', onChartAfterIsInsiderPlot); addEvent(PointerClass, 'afterGetHoverData', onPointerAfterGetHoverData); addEvent(PointerClass, 'beforeGetHoverData', onPointerBeforeGetHoverData); addEvent(SeriesClass, 'setClip', onSetClip); } } /** * Check whether element is inside or outside pane. * @internal * @param {number} x * Element's x coordinate * @param {number} y * Element's y coordinate * @param {Array<number>} center * Pane's center (x, y) and diameter * @param {number} startAngle * Pane's normalized start angle in radians (<-PI, PI>) * @param {number} endAngle * Pane's normalized end angle in radians (<-PI, PI>) */ function isInsidePane(x, y, center, startAngle, endAngle) { let insideSlice = true; const cx = center[0], cy = center[1], twoPi = 2 * Math.PI; const distance = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2)); if (defined(startAngle) && defined(endAngle)) { // Round angle to N-decimals to avoid numeric errors let angle = Math.atan2(correctFloat(y - cy, 8), correctFloat(x - cx, 8)); // Normalize angle to [0, 2π) angle = (angle + twoPi) % (twoPi); startAngle = (startAngle + twoPi) % (twoPi); endAngle = (endAngle + twoPi) % (twoPi); // Ignore full circle panes: if (Math.abs(endAngle - startAngle) > 1e-6) { // If the normalized start angle is greater than the end angle, // it means the arc wraps around 0°. In this case, we check // if the angle falls into either [startAngle, 2π) or [0, endAngle]. if (startAngle > endAngle) { insideSlice = (angle >= startAngle || angle <= endAngle); } else { // In this case, we simply check if angle is within the // [startAngle, endAngle] range insideSlice = angle >= startAngle && angle <= endAngle; } } } else { // If no start/end angles are defined, treat it as a full circle insideSlice = true; } // Round up radius because x and y values are rounded return distance <= Math.ceil(center[2] / 2) && insideSlice; } /** * Check if (x, y) position is within pane for polar. * @internal */ function onChartAfterIsInsiderPlot(e) { const chart = this; if (chart.polar) { if (e.options.inverted) { [e.x, e.y] = [e.y, e.x]; } e.isInsidePlot = chart.pane.some((pane) => isInsidePane(e.x, e.y, pane.center, pane.axis && pane.axis.normalizedStartAngleRad, pane.axis && pane.axis.normalizedEndAngleRad)); } } /** * @internal */ function onPointerAfterGetHoverData(eventArgs) { const chart = this.chart; if (eventArgs.hoverPoint && eventArgs.hoverPoint.plotX && eventArgs.hoverPoint.plotY && chart.hoverPane && !isInsidePane(eventArgs.hoverPoint.plotX, eventArgs.hoverPoint.plotY, chart.hoverPane.center)) { eventArgs.hoverPoint = void 0; } } /** @internal */ function onPointerBeforeGetHoverData(eventArgs) { const chart = this.chart; if (chart.polar) { // Find pane we are currently hovering over. chart.hoverPane = chart.getHoverPane(eventArgs); // Edit filter method to handle polar eventArgs.filter = function (s) { return (s.visible && !(!eventArgs.shared && s.directTouch) && // #3821 pick(s.options.enableMouseTracking, true) && (!chart.hoverPane || s.xAxis.pane === chart.hoverPane)); }; } else { chart.hoverPane = void 0; } } /* * * * Default Export * * */ /** @internal */ const PaneComposition = { compose }; /** @internal */ export default PaneComposition;