uPlot icon indicating copy to clipboard operation
uPlot copied to clipboard

dynamic setting of series style opts

Open trentwatt opened this issue 2 years ago • 7 comments

Hi Leon,

RE: https://github.com/leeoniya/uPlot/blob/4805a2e002e914ff7b6a67a4666b014ab67b49fd/dist/uPlot.d.ts#L82

was wondering if you had any suggestions for implementing and/or were open to receiving PRs for setSeries to be able to take style opts.

trentwatt avatar Oct 19 '22 05:10 trentwatt

it depends on the use case. the only option mutation APIs i want to expose are ones where re-initializing the plot is too impractical (every mousemove event, every data streaming update, etc). for stuff like dynamically configuring options from a UI by the user my answer will almost always be "just re-init the plot".

so, make your case!

leeoniya avatar Oct 19 '22 11:10 leeoniya

use case is basically synced selection + focus between the rows of a table and the series of a chart.

with something like:

not selected -> stroke alpha = 0.2 selected -> stroke alpha = 0.6 hovered / hovered + selected -> stroke alpha = 1

where both hover as well as selection can come from the chart in addition the table.

trentwatt avatar Oct 19 '22 11:10 trentwatt

not sure if a use case constitutes "making my case." if need be i can argue it a little further 😃

trentwatt avatar Oct 19 '22 12:10 trentwatt

stroke and fill can be callbacks, so you can achieve this by supplying closures for these options and then relying on u.redraw(false, false).

https://github.com/leeoniya/uPlot/blob/4805a2e002e914ff7b6a67a4666b014ab67b49fd/dist/uPlot.d.ts#L728-L730

adding the ability to modify this via .setSeries would be more ergonomic but also a tiny bit slower, since internally stroke and fill would need to be rewrapped into identity functions: u.setSeries(i, {stroke: '#fff'}) would need to do u.series[i].stroke = () => opts.stroke before invoking redraw, which is not great for rapid hover changes!

i'll think about it.

leeoniya avatar Oct 19 '22 18:10 leeoniya

ah okay, thanks for the tip!

trentwatt avatar Oct 22 '22 02:10 trentwatt

Just to add something here:

I have some charts that have a pretty heavy state that is maintained only inside of the uplot object via a plugin. Data is loaded as the user scrolls forward and backward or zooms in via a plugin. I would like to update the axis and series colors to match their current selected MUI theme mode. But due to the statefulness of my uplot ref, reinitializing the graph isn't the best option for me.

The simplest way in my mind (this is a react component) is to have a useEffect hook that applies a new axis.grid.stroke, axis.tick.stroke, and axis.stroke based on my current palette. So something like a getAxis/setAxis, getSeries/setSeries option that you are considering would be great.

For anyone who may be facing a similar issue, I solved it for now by using a callback for all of my stroke colors, and using a useEffect hook to pass the current theme down to the uplot reference.

//use this interface as your ref type
interface uPlotExtension extends uPlot {
   theme:Theme 
}
//use this callback to set your colors
stroke: (u:uPlotExtenstion) => u.theme.palette.graphColors.gridlines

//In your uplot component, pass the theme down
let theme = useTheme()
let uplot= useRef<uPlotExtension|null>(null);
useEffect(()=>{
    if(uplot.current && theme){
	    uplot.current.theme = theme
    }
},[theme])

kbieber-dws avatar Dec 13 '22 16:12 kbieber-dws

I would like to update the axis and series colors to match their current selected MUI theme mode

themes change very infrequently, correct? like 0-2 times per user session?

leeoniya avatar Dec 13 '22 21:12 leeoniya