Skip to content

Events ​

Subscribe to chart events with chart.on and unsubscribe with chart.off:

ts
import type { PointerEventData } from '@mk7s/holochart';

function onClick(event: PointerEventData) {
  for (const point of event.points) {
    console.log(point.curveNumber, point.pointNumber, point.x, point.y);
  }
}

chart.on('click', onClick);
// later
chart.off('click', onClick);

chart.on also returns a function that unsubscribes, chart.once listens for one event only, and chart.off(name) without a listener removes every listener of that event. Listeners may unsubscribe while the event is being dispatched.

A listener that throws doesn't stop the other listeners or the chart: hover labels, zoom, pending updates and the afterplot event carry on as usual. The error is reported with the browser's reportError, so it shows up in the console and in error trackers as an uncaught error. The same applies to config.renderHover (the built-in labels are drawn instead) and to custom modebar buttons.

Event list ​

The payloads are typed: ChartEvents in the API reference maps each event name to its payload type, so chart.on infers the listener's argument.

EventWhen it firesPayload
clickData points are clicked (with clickmode including 'event', the default)points[], event
doubleclickThe plot area is double-clicked, after the double-click reset or selection clearing rannone
hoverThe pointer moves onto different points, or chart.hover() is calledpoints[], event, xvals and yvals (the pointer position in data units)
unhoverThe hovered points are gone: the pointer moved off them or left the chart, or chart.unhover()points (empty), event
sunburstclickA sunburst sector is clicked, before clickpoints[] (the sector), nextLevel; return false to cancel the drill-down
treemapclickA treemap tile or path bar segment is clicked, before clickpoints[] (the tile), nextLevel; return false to cancel the drill-down
icicleclickAn icicle cell or path bar segment is clicked, before clickpoints[] (the cell), nextLevel; return false to cancel the drill-down
selectingDuring a box or lasso selection drag, once per animation framepoints[], range or lassoPoints, selections, event
selectedA box or lasso selection completes, or a point is click-selected (clickmode: 'select')points[], range or lassoPoints, selections, event
deselectThe selection is cleared (a double-click, or a click on empty space in a select drag mode)none
relayoutLayout changed (zoom, pan, chart.relayout, chart.update)The changed layout paths and values
relayoutingDuring a drag or scroll zoom or pan, once per animation frame; a relayout follows at the endThe axis ranges shown so far, as layout paths ('xaxis.range[0]', …)
restyleTrace attributes changed (chart.restyle, chart.updateAttributes, a drill-down, a sankey node drop). Not emitted by chart.updateupdate (the changed paths and values) and traces (their indices)
redrawData added with chart.extendTraces or chart.prependTraces has been drawnkind ('extend' or 'prepend'), update, traces, maxPoints
resizeThe figure size changed (a container resize with config.responsive, or a relayout)width and height in CSS pixels
clickannotationAn annotation with captureevents: true (or an editable one) is clickedindex in layout.annotations, annotation, fullAnnotation, event
legendclickA legend item is clickedcurveNumber, data, fullData, label; return false to cancel the toggle
legenddoubleclickA legend item is double-clickedcurveNumber, data, fullData, label; return false to cancel the isolation
sliderchangeA layout slider's active step changesslider, step, interaction, previousActive
sliderstartA pointer is pressed on a sliderslider
sliderendThe pointer dragging a slider is releasedslider, step (the active step)
buttonclickedAn update-menu button is clicked, after its method was called (unless execute: false)menu, button, active (the menu's active index after the click), event
animatinganimate starts playing framesnone
animatingframeAn animation frame startsname, frame (the computed frame), animation (its frame and transition opts)
animatedAn animation finishes (no frame left to play)none
animationinterruptedQueued frames were dropped (mode: 'next' or 'immediate')none
transitioningA transition starts (a frame, or react with layout.transition)none
transitionedA transition finished and its final state is drawnnone
transitioninterruptedAnother transition cut a transition shortnone
afterplotAfter each update has been drawn (not after each frame of a transition)none
beforerenderBefore each rendered frametime, delta, frame, continuous
afterrenderAfter each rendered frametime, delta, frame, continuous
webglcontextlostThe browser dropped the WebGL contextnone
webglcontextrestoredThe WebGL context came back and the chart re-renderednone
destroyThe chart was destroyed (chart.destroy() or purge(el))none

event is the DOM event behind a pointer event. It is absent when the event has no DOM event behind it, such as chart.hover() or a click on a hierarchy node.

Frames render only when something changes, so beforerender and afterrender do not fire on every browser animation frame. Their payload object is reused between frames; read the three.js objects from chart.three (scene, renderer, …). See three.js objects.

The animation and transition events are covered in more detail in Transitions & animation.

Points ​

Each entry in points[] describes one point, shaped like Plotly's event points:

FieldContents
curveNumberTrace index
pointNumber / pointIndexIndex into the trace's data arrays; [row, column] for a cell of a heatmap or image
pointNumbersEvery data index behind an aggregated point (a histogram bin, a stacked segment)
x, y, zData values (numbers, dates, category names); z in 3D and on grids
customdataThe point's customdata entry
text, hovertextThe point's text and hovertext entries
data, fullDataThe input trace, and the trace after defaults
xaxis, yaxisThe point's axes
bboxWhere the hover label anchors, in container pixels (x0, x1, y0, y1; hover and click)

Traces add fields of their own: pie slices carry label, value and percent, hierarchy nodes and sankey nodes and links carry the fields listed below. The full type is ChartPoint.

Cancelling default actions ​

A listener that returns false cancels the default action of these events:

  • legendclick: the visibility toggle of the clicked trace (or legend group).
  • legenddoubleclick: the isolation of the double-clicked trace.
  • sunburstclick, treemapclick and icicleclick: the drill-down, and the click event that would follow.
  • click on a sunburst, treemap or icicle: the drill-down.

Every listener still runs; one false is enough to cancel. Returning anything else, or nothing, lets the default happen.

Hierarchy clicks ​

A click on a sunburst sector, a treemap tile or an icicle cell (or a treemap or icicle path bar segment) emits sunburstclick, treemapclick or icicleclick first, then click (when clickmode includes 'event' and hovermode is not false). If no listener of either returned false, the chart drills to nextLevel: it writes it to the trace's level with a GUI restyle (so a restyle event follows) and animates the change unless reduced motion is on. Clicks during the drill animation emit their events but don't drill.

The payload, HierarchyClickEventData, has:

  • points: one point, the clicked node. Besides curveNumber, pointNumber, data, fullData, customdata, text, hovertext and bbox, it carries the node's label, value, id, color, parent (the parent's label; absent on the root), currentPath (the labels from the root down to the parent, as 'All/A/'), entry (the label of the node currently shown as the root), root (the hierarchy root's label), and percentParent, percentEntry and percentRoot (the node's share of its parent, of the current root, and of the whole, from 0 to 1).
  • nextLevel: the level the click leads to, the id of a node ('' for the whole hierarchy of a trace with several roots):
    • sunburst: the clicked sector, or the level above for the center. It is absent on the root of the hierarchy and on leaves, which don't drill.
    • treemap and icicle: the clicked tile (leaves too), the level above for the current root, or the clicked path bar segment's node. It is always set; clicking the hierarchy root when it is already shown gives its own level and drills nowhere.

Return false to keep the chart where it is, for example to open a detail view instead:

ts
import type { HierarchyClickEventData } from '@mk7s/holochart';

function onSunburstClick(event: HierarchyClickEventData) {
  const node = event.points[0];
  if (node?.['label'] === 'Other') {
    console.log('show details for', node['currentPath']);
    return false; // no drill-down, no click event
  }
  return true;
}

chart.on('sunburstclick', onSunburstClick);

See the Interactivity sections of Sunburst, Treemap and Icicle for the drill-down itself.

A sankey trace emits the usual hover, unhover and click events; there is no sankey-specific event. Each point is either a node or a link, and carries Plotly's fields for it, with curveNumber and pointNumber (the node's index in the node arrays, or the link's in the link arrays).

Node fieldContents
labelThe node's label
valueThe node's value
colorIts fill color
customdataIts node.customdata entry
depthIts column, from 0
sourceLinksIndices of the links leaving it
targetLinksIndices of the links entering it
groupWhether it is a group node made by node.groups
childrenNodesThe node indices a group node combines (empty for other nodes)
Link fieldContents
labelThe link's label
valueThe link's value
colorIts fill color
customdataIts link.customdata entry
sourceThe source node, with the node fields above
targetThe target node, with the node fields above
flowThe links with the same source and target (see below)

flow has value (the total of those links), links (their indices), concentration (this link's share of the total) and labelConcentration (the share of the flow's links with this link's label).

Only links have source and target, so a listener can tell the two apart:

ts
chart.on('click', ({ points }) => {
  const point = points[0];
  if (point?.fullData.type !== 'sankey') return;
  if ('source' in point) {
    const source = point['source'] as { label: string };
    const target = point['target'] as { label: string };
    console.log(`link ${source.label} → ${target.label}: ${String(point['value'])}`);
  } else {
    console.log(`node ${String(point['label'])}`);
  }
});

Outside hovermode: 'closest', hovering a link reports every link of its flow. A hoverinfo (or node.hoverinfo, link.hoverinfo) of 'skip' turns hover and click events off for that part. Dropping a dragged node emits a restyle of node.x and node.y. See Sankey.

Plotly event names ​

Every event also answers to its Plotly name with a plotly_ prefix, such as plotly_click, plotly_relayout or plotly_sunburstclick: chart.on('plotly_click', …) subscribes to click. Code written for Plotly event handlers keeps working, on charts made with createChart and with the Plotly-style functional API (newPlot, which resolves to the chart) alike.

See also Interaction & events.

Released under the MIT License.