/**
* @typedef { import("./core.controller").default } Chart
* @typedef { import("../../types/index.esm").ChartEvent } ChartEvent
- * @typedef {{axis?: string, intersect?: boolean}} InteractionOptions
+ * @typedef {{axis?: string, intersect?: boolean, includeInvisible?: boolean}} InteractionOptions
* @typedef {{datasetIndex: number, index: number, element: import("./core.element").default}} InteractionItem
* @typedef { import("../../types/index.esm").Point } Point
*/
* @param {Point} position - the point to be nearest to, in relative coordinates
* @param {string} axis - the axis mode. x|y|xy|r
* @param {boolean} [useFinalPosition] - use the element's animation target instead of current position
+ * @param {boolean} [includeInvisible] - include invisible points that are outside of the chart area
* @return {InteractionItem[]} the nearest items
*/
-function getIntersectItems(chart, position, axis, useFinalPosition) {
+function getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) {
const items = [];
- if (!chart.isPointInArea(position)) {
+ if (!includeInvisible && !chart.isPointInArea(position)) {
return items;
}
const evaluationFunc = function(element, datasetIndex, index) {
- if (!_isPointInArea(element, chart.chartArea, 0)) {
+ if (!includeInvisible && !_isPointInArea(element, chart.chartArea, 0)) {
return;
}
if (element.inRange(position.x, position.y, useFinalPosition)) {
* @param {string} axis - the axes along which to measure distance
* @param {boolean} [intersect] - if true, only consider items that intersect the position
* @param {boolean} [useFinalPosition] - use the element's animation target instead of current position
+ * @param {boolean} [includeInvisible] - include invisible points that are outside of the chart area
* @return {InteractionItem[]} the nearest items
*/
-function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition) {
+function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
let items = [];
const distanceMetric = getDistanceMetricForAxis(axis);
let minDistance = Number.POSITIVE_INFINITY;
}
const center = element.getCenterPoint(useFinalPosition);
- const pointInArea = chart.isPointInArea(center);
+ const pointInArea = !!includeInvisible || chart.isPointInArea(center);
if (!pointInArea && !inRange) {
return;
}
* @param {string} axis - the axes along which to measure distance
* @param {boolean} [intersect] - if true, only consider items that intersect the position
* @param {boolean} [useFinalPosition] - use the element's animation target instead of current position
+ * @param {boolean} [includeInvisible] - include invisible points that are outside of the chart area
* @return {InteractionItem[]} the nearest items
*/
-function getNearestItems(chart, position, axis, intersect, useFinalPosition) {
- if (!chart.isPointInArea(position)) {
+function getNearestItems(chart, position, axis, intersect, useFinalPosition, includeInvisible) {
+ if (!includeInvisible && !chart.isPointInArea(position)) {
return [];
}
return axis === 'r' && !intersect
? getNearestRadialItems(chart, position, axis, useFinalPosition)
- : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition);
+ : getNearestCartesianItems(chart, position, axis, intersect, useFinalPosition, includeInvisible);
}
/**
const position = getRelativePosition(e, chart);
// Default axis for index mode is 'x' to match old behaviour
const axis = options.axis || 'x';
+ const includeInvisible = options.includeInvisible || false;
const items = options.intersect
- ? getIntersectItems(chart, position, axis, useFinalPosition)
- : getNearestItems(chart, position, axis, false, useFinalPosition);
+ ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible)
+ : getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
const elements = [];
if (!items.length) {
dataset(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || 'xy';
+ const includeInvisible = options.includeInvisible || false;
let items = options.intersect
- ? getIntersectItems(chart, position, axis, useFinalPosition) :
- getNearestItems(chart, position, axis, false, useFinalPosition);
+ ? getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible) :
+ getNearestItems(chart, position, axis, false, useFinalPosition, includeInvisible);
if (items.length > 0) {
const datasetIndex = items[0].datasetIndex;
point(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || 'xy';
- return getIntersectItems(chart, position, axis, useFinalPosition);
+ const includeInvisible = options.includeInvisible || false;
+ return getIntersectItems(chart, position, axis, useFinalPosition, includeInvisible);
},
/**
nearest(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);
const axis = options.axis || 'xy';
- return getNearestItems(chart, position, axis, options.intersect, useFinalPosition);
+ const includeInvisible = options.includeInvisible || false;
+ return getNearestItems(chart, position, axis, options.intersect, useFinalPosition, includeInvisible);
},
/**