Skip to content

Commit

Permalink
Finalize exports; add docs and TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
joshkel committed Feb 15, 2022
1 parent 77de6ef commit 03de123
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 7 deletions.
53 changes: 53 additions & 0 deletions docs/configuration/interactions.md
Expand Up @@ -220,3 +220,56 @@ const chart = new Chart(ctx, {
}
});
```

## Custom Interaction Modes

New modes can be defined by adding functions to the `Chart.Interaction.modes` map. You can use the `Chart.Interaction.evaluateInteractionItems` function to help implement these.

Example:

```javascript
import { Interaction } from 'chart.js';
import { getRelativePosition } from 'chart.js/helpers';

/**
* Custom interaction mode
* @function Interaction.modes.myCustomMode
* @param {Chart} chart - the chart we are returning items from
* @param {Event} e - the event we are find things at
* @param {InteractionOptions} options - options to use
* @param {boolean} [useFinalPosition] - use final element position (animation target)
* @return {InteractionItem[]} - items that are found
*/
Interaction.modes.myCustomMode = function(chart, e, options, useFinalPosition) {
const position = getRelativePosition(e, chart);

const items = [];
Interaction.evaluateInteractionItems(chart, 'x', position, (element, datasetIndex, index) => {
if (element.inXRange(position.x, useFinalPosition) && myCustomLogic(element)) {
items.push({element, datasetIndex, index});
}
});
return items;
};

// Then, to use it...
new Chart.js(ctx, {
type: 'line',
data: data,
options: {
interaction: {
mode: 'myCustomMode'
}
}
})
```

If you're using TypeScript, you'll also need to register the new mode:

```typescript
declare module 'chart.js' {
interface InteractionModeMap {
myCustomMode: InteractionModeFunction;
}
}
```
13 changes: 8 additions & 5 deletions src/core/core.interaction.js
Expand Up @@ -43,14 +43,14 @@ function binarySearch(metaset, axis, value, intersect) {
}

/**
* Helper function to get items using binary search, when the data is sorted.
* Helper function to select candidate elements for interaction
* @param {Chart} chart - the chart
* @param {string} axis - the axis mode. x|y|xy|r
* @param {Point} position - the point to be nearest to, in relative coordinates
* @param {function} handler - the callback to execute for each visible item
* @param {boolean} [intersect] - consider intersecting items
*/
export function evaluateInteractionItems(chart, axis, position, handler, intersect) {
function evaluateInteractionItems(chart, axis, position, handler, intersect) {
const metasets = chart.getSortedVisibleDatasetMetas();
const value = position[axis];
for (let i = 0, ilen = metasets.length; i < ilen; ++i) {
Expand Down Expand Up @@ -89,7 +89,7 @@ function getDistanceMetricForAxis(axis) {
* @param {boolean} [useFinalPosition] - use the element's animation target instead of current position
* @return {InteractionItem[]} the nearest items
*/
export function getIntersectItems(chart, position, axis, useFinalPosition) {
function getIntersectItems(chart, position, axis, useFinalPosition) {
const items = [];

if (!chart.isPointInArea(position)) {
Expand Down Expand Up @@ -179,7 +179,7 @@ function getNearestCartesianItems(chart, position, axis, intersect, useFinalPosi
* @param {boolean} [useFinalPosition] - use the element's animation target instead of current position
* @return {InteractionItem[]} the nearest items
*/
export function getNearestItems(chart, position, axis, intersect, useFinalPosition) {
function getNearestItems(chart, position, axis, intersect, useFinalPosition) {
if (!chart.isPointInArea(position)) {
return [];
}
Expand All @@ -198,7 +198,7 @@ export function getNearestItems(chart, position, axis, intersect, useFinalPositi
* @param {boolean} [useFinalPosition] - use the element's animation target instead of current position
* @return {InteractionItem[]} the nearest items
*/
export function getAxisItems(chart, position, axis, intersect, useFinalPosition) {
function getAxisItems(chart, position, axis, intersect, useFinalPosition) {
const items = [];
const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange';
let intersectsItem = false;
Expand All @@ -223,6 +223,9 @@ export function getAxisItems(chart, position, axis, intersect, useFinalPosition)
* @namespace Chart.Interaction
*/
export default {
// Part of the public API to facilitate developers creating their own modes
evaluateInteractionItems,

// Helper function for different modes
modes: {
/**
Expand Down
18 changes: 16 additions & 2 deletions types/index.esm.d.ts
Expand Up @@ -509,6 +509,7 @@ export declare class Chart<
render(): void;
draw(): void;

isPointInArea(point: Point): boolean;
getElementsAtEventForMode(e: Event, mode: string, options: InteractionOptions, useFinalPosition: boolean): InteractionItem[];

getSortedVisibleDatasetMetas(): ChartMeta[];
Expand Down Expand Up @@ -741,6 +742,17 @@ export type InteractionMode = keyof InteractionModeMap;

export const Interaction: {
modes: InteractionModeMap;

/**
* Helper function to select candidate elements for interaction
*/
evaluateInteractionItems(
chart: Chart,
axis: InteractionAxis,
position: Point,
handler: (element: Element & VisualElement, datasetIndex: number, index: number) => void,
intersect?: boolean
): InteractionItem[];
};

export const layouts: {
Expand Down Expand Up @@ -1395,6 +1407,8 @@ export interface ChartComponent {
afterUnregister?(): void;
}

export type InteractionAxis = 'x' | 'y' | 'xy' | 'r';

export interface CoreInteractionOptions {
/**
* Sets which elements appear in the tooltip. See Interaction Modes for details.
Expand All @@ -1408,9 +1422,9 @@ export interface CoreInteractionOptions {
intersect: boolean;

/**
* Can be set to 'x', 'y', 'xy' or 'r' to define which directions are used in calculating distances. Defaults to 'x' for 'index' mode and 'xy' in dataset and 'nearest' modes.
* Defines which directions are used in calculating distances. Defaults to 'x' for 'index' mode and 'xy' in dataset and 'nearest' modes.
*/
axis: 'x' | 'y' | 'xy' | 'r';
axis: InteractionAxis;
}

export interface CoreChartOptions<TType extends ChartType> extends ParsingOptions, AnimationOptions<TType> {
Expand Down

0 comments on commit 03de123

Please sign in to comment.