Dynamically updating the range every 10 seconds

#1133 · closed · 7 comments

View on GitHub ↗

muenchris

I am trying to replace Smoothie Charts with uPlot. WIth Smoothie I can update the Min/Max (range) of the Y series at any time and the plot redraws accordingly and automatically. How can I do this with uPlot? I tried setScale but that did not work. I tried a dynamic range in the Options but that is only called when the options are applied at Chart create. I tried updating this.uPlotOptions.scales.y.range[1]=newRange and this.myChartControl.scales.y.range[1]=newRange The plot still is not changing its range at runtime. Is there a example that show how to dynamically change the (Y scale) range? my options are very simple: ``` uPlotOptions:uPlot.Options = { width: 100, height: 100, pxAlign: true, axes: [{ show: false }, { show: false }], // Clean look series: [ {} //New series are added at runtime ], legend: { show: false }, cursor: { show: false, }, scales: { x: { time: false, dir: -1 }, // -1 = left to right y: { // auto: false, range: (u, min, max) => { // return [this.rangeMin, this.rangeMax]; // } } // Full height } }; ```

Comments

leeoniya

are you able to post an example on jsfiddle of how you have this working currently in Smoothie Charts? and/or a screen rec?

muenchris

There is a online "builder" for Smoothiechart: http://smoothiecharts.org/builder/ this allows you to set a "Fixed Maximum scale" for the "Y-Scaling". If you toggle it, you can see how the chart updates right away. Smoothiechart has not been updated in many years and has issues with scaling and 3D transforms of the Canvas element. (see my fiddle example below). Here my scenario: [Fiddle Example](https://jsfiddle.net/muenchris/wfa9v5nd/) In my real application the change of the Scale will come from a backend that calculates the data. If you look at the right chart, it would adjust the scale every 3-5 seconds. The real data is not changing that linear and has a max value that can change over time.

leeoniya

i think there's a bit of a gotcha around `auto: false`, which i've wanted to fix. `auto: false` currently implies that the scale is fully static, and it avoids scanning the data to auto-range from it. the effect is that it will not call `scale.range` either, since the assumption is that it will not change. i'd like to change this so that `scale.range()` is called regardless of the `scale.auto` setting. for now, i think you should be able to use the range callback with `auto: true`, but you'll incur a small perf penalty for scanning the data to get the dataMin and dataMax values to be passed into that range fn, which you'll just ignore. https://jsfiddle.net/k0wd7otc/ ```js let data = [ [0, 1, 2], [2, 3, 5], ]; function randRange() { let a = Math.random() * 100; let b = Math.random() * 100; return [Math.min(a, b), Math.max(a, b)]; } let range = randRange(); const opts = { width: 800, height: 400, scales: { x: { time: false, }, y: { auto: true, range: (u, min, max) => { return range; }, }, }, series: [ {}, { stroke: 'red', }, ], }; let u = new uPlot(opts, data, document.body); setInterval(() => { range = randRange(); u.redraw(); }, 1000); ```

muenchris

I see, the function at the "range:" option is called everytime redraw() is called. I think I can live with that. I bascially have to do a u.redraw() everytime my range values change (coming down from the backend). calling setData(mydata, true) alone is not calling the u.redraw()?

leeoniya

using `setData(data)` works as well, it calls redraw internally. the key here is leaving "auto: true" for now to ensure that the scale.range function is called. i'll look at fixing this in the next couple days.

muenchris

I tried this first with a function on the range: option and just using setData() but the range function was not called. I will try this again with an explicit call to redraw() after setData().

leeoniya

finally fixed :) https://leeoniya.github.io/uPlot/demos/issues/issue-1133-dynamic-backend-range.html