highcharts
Version:
JavaScript charting framework
133 lines (132 loc) • 4.3 kB
JavaScript
/* *
*
* Imports
*
* */
import U from '../../Core/Utilities.js';
const { addEvent, correctFloat, defined, pick } = U;
/* *
*
* Functions
*
* */
/** @private */
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;
}
/** @private */
function compose(ChartClass, PointerClass) {
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);
}
}
/**
* Check whether element is inside or outside pane.
* @private
* @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];
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
const angle = Math.atan2(correctFloat(y - cy, 8), correctFloat(x - cx, 8));
// Ignore full circle panes:
if (endAngle !== startAngle) {
// If normalized start angle is bigger than normalized end,
// it means angles have different signs. In such situation we
// check the <-PI, startAngle> and <endAngle, PI> ranges.
if (startAngle > endAngle) {
insideSlice = (angle >= startAngle &&
angle <= Math.PI) || (angle <= endAngle &&
angle >= -Math.PI);
}
else {
// In this case, we simple check if angle is within the
// <startAngle, endAngle> range
insideSlice = angle >= startAngle &&
angle <= correctFloat(endAngle, 8);
}
}
}
// 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.
* @private
*/
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));
}
}
/**
*
*/
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;
}
}
/** @private */
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
*
* */
const PaneComposition = {
compose
};
export default PaneComposition;