Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable interaction mode support for events (#659)
* Enable events triggering on all affected annotations * removes commented code * removes useless if statements * first interaction mode implementation * removes useless callback * applies interaction mode to click events * applies review * removes array creation if not needed * interaction for box annotation * adds test cases to box.spec * adds ellipse to interaction management * adds label to interaction management * adds point to interaction management * adds polygon to interaction management * should fix CC on box * removes inX/YRange going to a unique method inRange * adds line to interaction management * adds mode x and y * removes tabs * fixes similar code and adds point to the context of interaction tests * adds types * orders the options in types for annotation node * adds documentation * fixes typo on doc * fixes CC for function with 5 arguments (exceeds 4 allowed) * adds note about the breaking change using interaction * Update docs/guide/migrationV2.md Co-authored-by: Jukka Kurkela <jukka.kurkela@gmail.com> Co-authored-by: Jukka Kurkela <jukka.kurkela@gmail.com>
- Loading branch information
1 parent
17352cd
commit e8bd9c0
Showing
23 changed files
with
731 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import {distanceBetweenPoints} from 'chart.js/helpers'; | ||
|
||
const interaction = { | ||
modes: { | ||
/** | ||
* Point mode returns all elements that hit test based on the event position | ||
* @param {Object} state - the state of the plugin | ||
* @param {ChartEvent} event - the event we are find things at | ||
* @return {Element[]} - elements that are found | ||
*/ | ||
point(state, event) { | ||
return filterElements(state, event, {intersect: true}); | ||
}, | ||
|
||
/** | ||
* Nearest mode returns the element closest to the event position | ||
* @param {Object} state - the state of the plugin | ||
* @param {ChartEvent} event - the event we are find things at | ||
* @param {Object} options - interaction options to use | ||
* @return {Element[]} - elements that are found (only 1 element) | ||
*/ | ||
nearest(state, event, options) { | ||
return getNearestItem(state, event, options); | ||
}, | ||
/** | ||
* x mode returns the elements that hit-test at the current x coordinate | ||
* @param {Object} state - the state of the plugin | ||
* @param {ChartEvent} event - the event we are find things at | ||
* @param {Object} options - interaction options to use | ||
* @return {Element[]} - elements that are found | ||
*/ | ||
x(state, event, options) { | ||
return filterElements(state, event, {intersect: options.intersect, axis: 'x'}); | ||
}, | ||
|
||
/** | ||
* y mode returns the elements that hit-test at the current y coordinate | ||
* @param {Object} state - the state of the plugin | ||
* @param {ChartEvent} event - the event we are find things at | ||
* @param {Object} options - interaction options to use | ||
* @return {Element[]} - elements that are found | ||
*/ | ||
y(state, event, options) { | ||
return filterElements(state, event, {intersect: options.intersect, axis: 'y'}); | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Returns all elements that hit test based on the event position | ||
* @param {Object} state - the state of the plugin | ||
* @param {ChartEvent} event - the event we are find things at | ||
* @param {Object} options - interaction options to use | ||
* @return {Element[]} - elements that are found | ||
*/ | ||
export function getElements(state, event, options) { | ||
const mode = interaction.modes[options.mode] || interaction.modes.nearest; | ||
return mode(state, event, options); | ||
} | ||
|
||
function inRangeByAxis(element, event, axis) { | ||
if (axis !== 'x' && axis !== 'y') { | ||
return element.inRange(event.x, event.y, 'x', true) || element.inRange(event.x, event.y, 'y', true); | ||
} | ||
return element.inRange(event.x, event.y, axis, true); | ||
} | ||
|
||
function getPointByAxis(event, center, axis) { | ||
if (axis === 'x') { | ||
return {x: event.x, y: center.y}; | ||
} else if (axis === 'y') { | ||
return {x: center.x, y: event.y}; | ||
} | ||
return center; | ||
} | ||
|
||
function filterElements(state, event, options) { | ||
return state.visibleElements.filter((element) => options.intersect ? element.inRange(event.x, event.y) : inRangeByAxis(element, event, options.axis)); | ||
} | ||
|
||
function getNearestItem(state, event, options) { | ||
let minDistance = Number.POSITIVE_INFINITY; | ||
|
||
return filterElements(state, event, options) | ||
.reduce((nearestItems, element) => { | ||
const center = element.getCenterPoint(); | ||
const evenPoint = getPointByAxis(event, center, options.axis); | ||
const distance = distanceBetweenPoints(event, evenPoint); | ||
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; | ||
}, []) | ||
.sort((a, b) => a._index - b._index) | ||
.slice(0, 1); // return only the top item; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.