I am using LightningChart JS library (https://www.npmjs.com/package/@lightningchart/lcjs) to display several line trends with scrolling time window. The data is coming over from websocket in real-time.
In the library, there is built-in functionality that I can place my mouse over the chart and there is a popup showing the nearest values from all the trends. This is very good, but I need it to behave a bit differently. Instead of an obstructive popup, I need the values to be displayed on the side. To understand better, please see this interactive chart as a starting point for my problem:
const {
lightningChart, Themes, LegendPosition,
AxisScrollStrategies, AxisTickStrategies
} = lcjs
const lc = lightningChart()
const chart = lc.ChartXY({
theme: Themes.light,
defaultAxisX: {
type: 'linear-highPrecision'
},
legend: {
position: LegendPosition.TopLeft
}
})
chart.setTitle('')
chart.axisX
.setScrollStrategy(AxisScrollStrategies.scrolling)
.setTickStrategy(AxisTickStrategies.DateTime)
.setInterval({ start: 0, end: 10000, stopAxisAfter: false })
const series1 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 1')
const series2 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 2')
const series3 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 3')
setInterval(() => {
const x = Date.now()
series1.appendSample({ x, y: Math.random() })
series2.appendSample({ x, y: Math.random() * 10 })
series3.appendSample({ x, y: -Math.random() * 5 })
}, 1000/60)
<script src="https://cdn.jsdelivr.net/npm/@lightningchart/lcjs@8.0.2/dist/lcjs.iife.js"></script>
Note the legend in top left. Ideally I would want the currently pointed values to be displayed there. Currently it says "Trend 1", "Trend 2", etc. always. When mouse is over the chart, I'd want them to show like this "Trend 1: 10.1"
I found the cursor documentation here https://lightningchart.com/js-charts/docs/features/cursor/#custom-cursors Most notably there is "Custom cursors" section, which does mention the availability of an API to plug in custom cursor logic. I tried adding this:
chart.setCustomCursor((event) => {
console.log(event)
})
The result is something like this:
{
hits: [
cursorPosition,
iSample,
x,
y,
sample,
...
]
}
The y value is everything I need, so this is good. But I haven't been able to find the way to connect this to the legend. I found the following potential APIs but didn't really even know what parameters to give them:
The cursor formatting override seemed most promising but I don't think it works together with setCustomCursor as it doesn't seem to affect anything in the console debug.
I think the right solution is something under chart.legend.setOptions but I can't seem to find the right syntax.
chart.legend.setEntryOptions is the most suitable API here. The first argument is a series object (in your case, series1/series2/series3, and second option lets you supply any kind of options that the legend entry for that specific series supports. For example, the text displayed.
setCustomCursor is also suitable API here, but in my opinion using cursortargetchange event gives better results. The difference is that using setCustomCursor completely disables the built-in cursor. It has its pros and cons, but I assume in your case you would still like for some elements of the built-in cursor to remain, such as the vertical splitter, X value marker and so on.
See edited code snippet from your question:
const {
lightningChart, Themes, LegendPosition,
AxisScrollStrategies, AxisTickStrategies
} = lcjs
const lc = lightningChart()
const chart = lc.ChartXY({
theme: Themes.light,
defaultAxisX: {
type: 'linear-highPrecision'
},
legend: {
position: LegendPosition.TopLeft
}
})
chart.setTitle('')
chart.axisX
.setScrollStrategy(AxisScrollStrategies.scrolling)
.setTickStrategy(AxisTickStrategies.DateTime)
.setInterval({ start: 0, end: 10000, stopAxisAfter: false })
const series1 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 1').setMaxSampleCount(100000)
const series2 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 2').setMaxSampleCount(100000)
const series3 = chart.addLineSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } }).setName('Trend 3').setMaxSampleCount(100000)
setInterval(() => {
const x = Date.now()
series1.appendSample({ x, y: Math.random() })
series2.appendSample({ x, y: Math.random() * 10 })
series3.appendSample({ x, y: -Math.random() * 5 })
}, 1000/60)
// Remove undesired parts from built-in cursor
chart.setCursor(cursor => cursor
.setResultTableVisible(false)
.setTickMarkerYVisible(false)
.getGridStrokeYStyle(lcjs.emptyLine)
)
// Show pointed values in legend
chart.addEventListener('cursortargetchange', (event) => {
if (event.hits) {
event.hits.forEach(hit => {
chart.legend.setEntryOptions(hit.series, {
text: `${hit.series.getName()}: ${hit.axisY.formatValue(hit.y)}`
})
})
} else {
chart.getSeries().forEach(series => {
chart.legend.setEntryOptions(series, { text: undefined })
})
}
})
<script src="https://cdn.jsdelivr.net/npm/@lightningchart/lcjs@8.0.2/dist/lcjs.iife.js"></script>