leeoniya / uPlot

📈 A small, fast chart for time series, lines, areas, ohlc & bars
MIT License
8.51k stars 371 forks source link

Streaming Data with a zoom level on #505

Closed Manuelbaun closed 3 years ago

Manuelbaun commented 3 years ago

Hi Guys,

I am trying to make a line chart use streaming data, like it was done here :https://leeoniya.github.io/uPlot/demos/stream-data.html

but I am only want to enable to user, to zoom in and watch the stream. At the moment, when using React, the Chart resets to no zoom level. And when not using React, this does not seem to work

  uplot?.setData(data, false)
  uplot?.redraw(true, true)

any ideas?

Thank you very much in advance

leeoniya commented 3 years ago

uPlot's zoom works by using a {min: timestamp, max: timestamp}. if you zoom to a min/max range while streaming, then that range will no longer "stream", because it is static. you have to update the min/max with every data update to a new timestamp range. how you update that timestamp range is up to you. do you want to zoom to {min: now - 10s, max: now}, to {min: now - 30s, max: now - 10s}. you can also "zoom" by doing setData() on only a portion of the full data.

please describe specifically what you're looking for.

Manuelbaun commented 3 years ago

@leeoniya thank you, I think you've answered it. I will give it a try to use {min: now - 10s, max: now}. That should do it

guanicoe commented 3 years ago

I wish to reopen this topic as I don't get the answer. Using the stream option, as said, the graph rests itself when setData is called. I does one prevent this from happening when a zoom in is done?

In other words, I wish to be able to zoom in a between given values to check some data. And only when I double click the graph should it reset and stream. I'm not sure how the answer {min: now - 10s, max: now} helps...

by the way, found out about this library this evening and it looks great. Good job!

leeoniya commented 3 years ago

setData() has a second argument that allows you to skip redraw and x-autoscaling: https://github.com/leeoniya/uPlot/blob/master/dist/uPlot.d.ts#L66

if you call it with false, you can then follow up with setScale('x') to scale to whatever you need, or just do nothing if already zoomed.

it's probably worth adding something like this to the streaming demos. i wanted to keep them pretty clean, but this comes up often. if you want to take a stab at it, i can answer questions, but i don't have time to write it myself currently.

guanicoe commented 3 years ago

ok, this could work. I just have a silly question... How do I determine if i'm zoomed?

guanicoe commented 3 years ago

If I get it working, I'll try putting some code together and push it to your repo if it can save you time

leeoniya commented 3 years ago

How do I determine if i'm zoomed?

probably check u.scales.x.min against u.data[0][0] and u.scales.x.max against u.data[0][u.data[0].length - 1].

guanicoe commented 3 years ago

great, this works! I guess the last step is to be able to zoom horizontally, but from what i read on other issues, this seems to be another challenge

leeoniya commented 3 years ago

zoom horizontally

?

guanicoe commented 3 years ago

zoom on the yaxis. with the current lib, I can only zoom on the x axis. I used plotly before uplot and depending on the cursor movement it selected either x,y or both axes. plotly was laggy with large datasets hence my switch to uplot.

leeoniya commented 3 years ago

https://leeoniya.github.io/uPlot/demos/zoom-variations.html

guanicoe commented 3 years ago

This is great. But how would you solve the fact that when zooming horizontally, I cannot use u.scales.x.min > 0? I tried doing comparison with u.series[0].min but I get false positives...

leeoniya commented 3 years ago

you should set cursor.drag.setScale: false, which disables native zoom on mouseup, and then use the setSelect hook to DIY zoom via .setScale(). see: https://github.com/leeoniya/uPlot/blob/master/demos/zoom-fetch.html