User interactions
LightningChart JS components come with a set of built-in user interactions.
Some of them are enabled by default, others not.
With some charts, the default enabled interactions can even vary based on the chart structure, most notably true for ChartXY where axis types, scroll strategies and series used may correspond to different default interaction scheme.
The method setUserInteractions can be used to tweak, configure and override the default set of user interactions:
// Example, rectangle zoom with mouse drag, zoom with wheel, pan with mouse wheel and CTRL pressed
chart.setUserInteractions({
rectangleZoom: {
lmb: {},
rmb: {},
},
zoom: {
wheel: {},
ctrl: { wheel: false },
},
pan: {
sensitivity: 2,
drag: false,
ctrl: {
wheel: {},
},
},
restorePrevious: false,
})
// Example, disable all user interactions
chart.setUserInteractions(undefined)
// Example, restore default interactions
chart.setUserInteractions({})
This method is used to override any selection of the available built-in interactions. These are numerous, and not all of them are enabled by default (as some conflict between others).
As seen from the above example, the API allows very delicate control, for example enabling specific interactions depending on which mouse button is used or if ctrl/shift/alt is pressed down.
When using setUserInteractions its important to remember that this method overrides the supplied information only, any unspecified properties retain their default values. For example, in above snippet the "restoreDefault" interaction retains its default behavior as it is unspecified.
In majority of cases, setUserInteractions accepts an object where key identifies the targeted user interaction (such as "panning", "zooming", etc.).
To disable an interaction entirely, you can pass false as its value, otherwise empty object ({}) signifies that the interaction is enabled without any overrides.
Situational overrides
Any interaction can have separate override states based on following global states:
- Ctrl-key down
- Shift-key down
- Alt-key down
- LMB used
- RMB used
- MMB used
chart.setUserInteractions({
pan: {
rmb: {
drag: false, // disable drag to pan on RMB
},
lmb: {
drag: {}, // enable drag to pan on LMB
},
},
rectangleZoom: false, // disable rectangle zoom - otherwise there are 2 conflicting interactions
})
Source overrides
1 interaction can be triggered from various different sources. For this reason, interactions can also have source specific overrides, which allow disabling that source or changing its behavior:
chart.setUserInteractions({
pan: {
// disable pan on mouse drag
drag: false,
lmb: { drag: false },
rmb: { drag: false },
wheel: {}, // ...but enable it when using mouse wheel
},
zoom: {
wheel: false, // disable mouse wheel zoom - otherwise there are 2 conflicting interactions
},
})
Practical tips
The API of setUserInteractions is quite complicated as it has many layers of overrides and by nature is a very flexible method that can do many things instead of just few different things.
By far, the easiest use experience is with type checking enabled.
The API is strongly typed, so you will receive suggestions on what can be done and warnings if attempting to do something unsupported.
If your development environment doesn't have type checking, maybe the best solution is to open one of our online examples in editor mode and experiment there.
However, keep in mind that the default user interactions can vary based on the structure of charts, so if the example is structurally very different from your application there might be functional differences.
When configuring enabled user interactions, it can be very helpful to debug the value of console.log(chart.getUserInteractions()) to understand the active configuration.
Examples
Examples of using setUserInteractions vary based on the object in question.
Here's a list to feature examples of most commonly used classes (not conclusive).
Custom user interactions
In case where a required user interaction is not supported built-in, you can either:
- Confirm from LightningChart whether this is indeed the case, and request its addition.
- Implement it yourself as a custom interaction.
The process of implementing a custom interaction is as follows:
- Disable any conflicting built-in user interactions
// Example, custom interaction with dragging LMB mouse in chart area, disable conflicting interactions
chart.setUserInteractions({
pan: {
lmb: false,
rmb: { drag: {} },
},
rectangleZoom: {
lmb: false,
rmb: false,
},
})
- Add event listeners to track user interactions, in this case pressing mouse down and moving it.
chart.seriesBackground.addEventListener('pointerdown', (eventDown) => {
if (eventDown.button !== 0) return
let prevCoord = eventDown
const handleMove = (eventMove: PointerEvent) => {
const delta = { x: eventMove.clientX - prevCoord.clientX, y: eventMove.clientY - prevCoord.clientY }
prevCoord = eventMove
// apply drag interaction here
}
const handleUp = (eventUp: PointerEvent) => {
chart.engine.container.removeEventListener('pointermove', handleMove)
chart.engine.container.removeEventListener('pointerup', handleUp)
}
chart.engine.container.addEventListener('pointermove', handleMove)
chart.engine.container.addEventListener('pointerup', handleUp)
})
chart.seriesBackground is an event interface that allows users to add event listeners for interactions on the series background. For other purposes, other similar interfaces exist such as: chart.background, chart.title, axis.title.
The above example is a very common boilerplate for tracking "dragging" events. They key part there is that pointerdown event is detected on the specific interactable object, whereas pointermove and pointerup are tracked globally, in this example using the container <div> of the chart.
If you want same customer interaction to apply on series background as well as over series, then it can be convenient to disable event tracking on series with series.setPointerEvents(false)
Drag & drop
Interactable LightningChart JS objects can be used as sources and targets for HTML drag & drop. This works like usual, by using draggable property and dragstart, dragover and drop events:
// Example, make stacked Y axes re-arrangeable by drag & drop
axisY.setUserInteractions({ rectangleZoom: false })
axisY.draggable = true
axisY.addEventListener('dragstart', (event) => {
if (!event.dataTransfer) return
event.dataTransfer.setData('text', JSON.stringify({ title: axisY.getTitle() }))
})
axisY.addEventListener('dragover', (event) => {
event.preventDefault()
})
axisY.addEventListener('drop', (event) => {
if (!event.dataTransfer) return
const srcTitle = JSON.parse(event.dataTransfer.getData('text')).title
if (!srcTitle) return
chart.swapAxes(axisY, chart.getAxes().find(axis => axis.getTitle() === srcTitle))
})
Frequently asked configurations
Swap left and right mouse buttons
chart.setUserInteractions({
pan: {
lmb: { drag: {} },
rmb: false,
},
rectangleZoom: {
lmb: false,
rmb: {},
},
})