İlk temizlik tamamlandı bir önceki projeden
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
'use strict';
|
||||
|
||||
var helpers = require('../helpers/index');
|
||||
|
||||
/**
|
||||
* Helper function to get relative position for an event
|
||||
* @param {Event|IEvent} event - The event to get the position for
|
||||
* @param {Chart} chart - The chart
|
||||
* @returns {object} the event position
|
||||
*/
|
||||
function getRelativePosition(e, chart) {
|
||||
if (e.native) {
|
||||
return {
|
||||
x: e.x,
|
||||
y: e.y
|
||||
};
|
||||
}
|
||||
|
||||
return helpers.getRelativePosition(e, chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to traverse all of the visible elements in the chart
|
||||
* @param {Chart} chart - the chart
|
||||
* @param {function} handler - the callback to execute for each visible item
|
||||
*/
|
||||
function parseVisibleItems(chart, handler) {
|
||||
var metasets = chart._getSortedVisibleDatasetMetas();
|
||||
var metadata, i, j, ilen, jlen, element;
|
||||
|
||||
for (i = 0, ilen = metasets.length; i < ilen; ++i) {
|
||||
metadata = metasets[i].data;
|
||||
for (j = 0, jlen = metadata.length; j < jlen; ++j) {
|
||||
element = metadata[j];
|
||||
if (!element._view.skip) {
|
||||
handler(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the items that intersect the event position
|
||||
* @param {ChartElement[]} items - elements to filter
|
||||
* @param {object} position - the point to be nearest to
|
||||
* @return {ChartElement[]} the nearest items
|
||||
*/
|
||||
function getIntersectItems(chart, position) {
|
||||
var elements = [];
|
||||
|
||||
parseVisibleItems(chart, function(element) {
|
||||
if (element.inRange(position.x, position.y)) {
|
||||
elements.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the items nearest to the event position considering all visible items in teh chart
|
||||
* @param {Chart} chart - the chart to look at elements from
|
||||
* @param {object} position - the point to be nearest to
|
||||
* @param {boolean} intersect - if true, only consider items that intersect the position
|
||||
* @param {function} distanceMetric - function to provide the distance between points
|
||||
* @return {ChartElement[]} the nearest items
|
||||
*/
|
||||
function getNearestItems(chart, position, intersect, distanceMetric) {
|
||||
var minDistance = Number.POSITIVE_INFINITY;
|
||||
var nearestItems = [];
|
||||
|
||||
parseVisibleItems(chart, function(element) {
|
||||
if (intersect && !element.inRange(position.x, position.y)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var center = element.getCenterPoint();
|
||||
var distance = distanceMetric(position, center);
|
||||
if (distance < minDistance) {
|
||||
nearestItems = [element];
|
||||
minDistance = distance;
|
||||
} else if (distance === minDistance) {
|
||||
// Can have multiple items at the same distance in which case we sort by size
|
||||
nearestItems.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
return nearestItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a distance metric function for two points based on the
|
||||
* axis mode setting
|
||||
* @param {string} axis - the axis mode. x|y|xy
|
||||
*/
|
||||
function getDistanceMetricForAxis(axis) {
|
||||
var useX = axis.indexOf('x') !== -1;
|
||||
var useY = axis.indexOf('y') !== -1;
|
||||
|
||||
return function(pt1, pt2) {
|
||||
var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
|
||||
var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
|
||||
return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
|
||||
};
|
||||
}
|
||||
|
||||
function indexMode(chart, e, options) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
// Default axis for index mode is 'x' to match old behaviour
|
||||
options.axis = options.axis || 'x';
|
||||
var distanceMetric = getDistanceMetricForAxis(options.axis);
|
||||
var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
|
||||
var elements = [];
|
||||
|
||||
if (!items.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
chart._getSortedVisibleDatasetMetas().forEach(function(meta) {
|
||||
var element = meta.data[items[0]._index];
|
||||
|
||||
// don't count items that are skipped (null data)
|
||||
if (element && !element._view.skip) {
|
||||
elements.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @interface IInteractionOptions
|
||||
*/
|
||||
/**
|
||||
* If true, only consider items that intersect the point
|
||||
* @name IInterfaceOptions#boolean
|
||||
* @type Boolean
|
||||
*/
|
||||
|
||||
/**
|
||||
* Contains interaction related functions
|
||||
* @namespace Chart.Interaction
|
||||
*/
|
||||
module.exports = {
|
||||
// Helper function for different modes
|
||||
modes: {
|
||||
single: function(chart, e) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
var elements = [];
|
||||
|
||||
parseVisibleItems(chart, function(element) {
|
||||
if (element.inRange(position.x, position.y)) {
|
||||
elements.push(element);
|
||||
return elements;
|
||||
}
|
||||
});
|
||||
|
||||
return elements.slice(0, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* @function Chart.Interaction.modes.label
|
||||
* @deprecated since version 2.4.0
|
||||
* @todo remove at version 3
|
||||
* @private
|
||||
*/
|
||||
label: indexMode,
|
||||
|
||||
/**
|
||||
* Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something
|
||||
* If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item
|
||||
* @function Chart.Interaction.modes.index
|
||||
* @since v2.4.0
|
||||
* @param {Chart} chart - the chart we are returning items from
|
||||
* @param {Event} e - the event we are find things at
|
||||
* @param {IInteractionOptions} options - options to use during interaction
|
||||
* @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
|
||||
*/
|
||||
index: indexMode,
|
||||
|
||||
/**
|
||||
* Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something
|
||||
* If the options.intersect is false, we find the nearest item and return the items in that dataset
|
||||
* @function Chart.Interaction.modes.dataset
|
||||
* @param {Chart} chart - the chart we are returning items from
|
||||
* @param {Event} e - the event we are find things at
|
||||
* @param {IInteractionOptions} options - options to use during interaction
|
||||
* @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
|
||||
*/
|
||||
dataset: function(chart, e, options) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
options.axis = options.axis || 'xy';
|
||||
var distanceMetric = getDistanceMetricForAxis(options.axis);
|
||||
var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
|
||||
|
||||
if (items.length > 0) {
|
||||
items = chart.getDatasetMeta(items[0]._datasetIndex).data;
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
/**
|
||||
* @function Chart.Interaction.modes.x-axis
|
||||
* @deprecated since version 2.4.0. Use index mode and intersect == true
|
||||
* @todo remove at version 3
|
||||
* @private
|
||||
*/
|
||||
'x-axis': function(chart, e) {
|
||||
return indexMode(chart, e, {intersect: false});
|
||||
},
|
||||
|
||||
/**
|
||||
* Point mode returns all elements that hit test based on the event position
|
||||
* of the event
|
||||
* @function Chart.Interaction.modes.intersect
|
||||
* @param {Chart} chart - the chart we are returning items from
|
||||
* @param {Event} e - the event we are find things at
|
||||
* @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
|
||||
*/
|
||||
point: function(chart, e) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
return getIntersectItems(chart, position);
|
||||
},
|
||||
|
||||
/**
|
||||
* nearest mode returns the element closest to the point
|
||||
* @function Chart.Interaction.modes.intersect
|
||||
* @param {Chart} chart - the chart we are returning items from
|
||||
* @param {Event} e - the event we are find things at
|
||||
* @param {IInteractionOptions} options - options to use
|
||||
* @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
|
||||
*/
|
||||
nearest: function(chart, e, options) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
options.axis = options.axis || 'xy';
|
||||
var distanceMetric = getDistanceMetricForAxis(options.axis);
|
||||
return getNearestItems(chart, position, options.intersect, distanceMetric);
|
||||
},
|
||||
|
||||
/**
|
||||
* x mode returns the elements that hit-test at the current x coordinate
|
||||
* @function Chart.Interaction.modes.x
|
||||
* @param {Chart} chart - the chart we are returning items from
|
||||
* @param {Event} e - the event we are find things at
|
||||
* @param {IInteractionOptions} options - options to use
|
||||
* @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
|
||||
*/
|
||||
x: function(chart, e, options) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
var items = [];
|
||||
var intersectsItem = false;
|
||||
|
||||
parseVisibleItems(chart, function(element) {
|
||||
if (element.inXRange(position.x)) {
|
||||
items.push(element);
|
||||
}
|
||||
|
||||
if (element.inRange(position.x, position.y)) {
|
||||
intersectsItem = true;
|
||||
}
|
||||
});
|
||||
|
||||
// If we want to trigger on an intersect and we don't have any items
|
||||
// that intersect the position, return nothing
|
||||
if (options.intersect && !intersectsItem) {
|
||||
items = [];
|
||||
}
|
||||
return items;
|
||||
},
|
||||
|
||||
/**
|
||||
* y mode returns the elements that hit-test at the current y coordinate
|
||||
* @function Chart.Interaction.modes.y
|
||||
* @param {Chart} chart - the chart we are returning items from
|
||||
* @param {Event} e - the event we are find things at
|
||||
* @param {IInteractionOptions} options - options to use
|
||||
* @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
|
||||
*/
|
||||
y: function(chart, e, options) {
|
||||
var position = getRelativePosition(e, chart);
|
||||
var items = [];
|
||||
var intersectsItem = false;
|
||||
|
||||
parseVisibleItems(chart, function(element) {
|
||||
if (element.inYRange(position.y)) {
|
||||
items.push(element);
|
||||
}
|
||||
|
||||
if (element.inRange(position.x, position.y)) {
|
||||
intersectsItem = true;
|
||||
}
|
||||
});
|
||||
|
||||
// If we want to trigger on an intersect and we don't have any items
|
||||
// that intersect the position, return nothing
|
||||
if (options.intersect && !intersectsItem) {
|
||||
items = [];
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user