dygraphs icon indicating copy to clipboard operation
dygraphs copied to clipboard

range selector in a graph with live data

Open mg1075 opened this issue 9 years ago • 7 comments

The range selector is awesome. http://dygraphs.com/tests/range-selector.html

But when the range selector is combined with a graph using live data, the default behavior is buggy.

Here is a jsbin for demonstration purposes: http://jsbin.com/nehitoxumu/1/edit?html,js,output

Everything seems fine when the range selector is at its full extended width and has not been moved.

But now let's say you want to move the range handles to a narrower time frame.

image

Fine.

But now the range slider has gone completely out of your control.

It starts moving on its own at the pace of the data update.

It moves to the left... image

...and continues moving to the left... image

...until finally, the range slider has mostly disappeared with only one handle remaining. image

The data in the upper (main chart) is frozen in place when the range slider starts moving left. When the range slider disappears, then the data in the upper chart also starts to disappear.

Is this a true bug? Maybe not, but this default behavior sure seems buggy.

The live data demo for highcharts exhibits similar behavior, but with at least two noticeable differences. http://www.highcharts.com/stock/demo/dynamic-update

(1). When the right-most range handle is at the right-most portion of the range selector, the range selector does not start sliding backwards. You can see data flowing through it. (2). When the left-most range handle is at the left-most portion of the range selector, the range selector does not continue to get pushed off the screen. You can see data flowing through it.

Is there a working dygraphs example of how to make the dygraphs range slider behave in a less buggy manner?

I'm sorry if I already posted the same issue on stackoverflow; danvk did recommend in a comment to use updateOptions, but that is not enough for me to get rolling.

mg1075 avatar Apr 07 '15 18:04 mg1075

The demo (& the jsbin) are dropping the left-most point on every update. So the data domain is changing.

By default the zoom range is "all the data". When you use the range selector to change it, the zoom range becomes a pair of specific dates. In the example you posted, as the data comes in updates, this will be an increasingly small fraction of the data domain and eventually the two won't intersect. That's why you see the behavior you do from the range selector.

The only part I see as a bug here is that the range selector handles get rendered outside the chart area when the zoom range and data domain don't intersect.

We could also potentially have support for half-pinned zoom ranges, i.e. value X to the most recent data point.

danvk avatar Apr 12 '15 19:04 danvk

You recommended elsewhere to use the updateOptions feature to reset the dateWindow for the range slider.

That takes care of the issue of the range slider falling off the screen, but then there the ability to manually slide the range handles or range selected section is lost. Is there a workaround?

http://jsfiddle.net/7w99t15x/

mg1075 avatar Apr 29 '15 21:04 mg1075

As danvk has said above, you will need to maintain the zoom range (aka dateWindow) outside of dygraphs. As you correctly surmised per your question in #617, you need to hook into the range selector events in order to do so. Probably the best way would be to add range selector events to the interaction model (if that has not already been done. I have not been following the latest dygraphs work.)

When I created the dygraphs-dynamiczooming-examples a while back, I used a more direct approach. Here is a rough jsfiddle showing that technique, using your jsfiddle as a base:

  • http://jsfiddle.net/kaliatech/q0xuomf3/

Although this basically works, you'll notice it has some issues. Mainly, you must release the mouse button when changing the range selectors before the next data load. (To keep that from being overly annoying, I modified the data load interval to 2 seconds.) A complete implementation of this would probably need to disable dynamic data loading while user interaction was in progress, although there are some other approaches that might be correct as well.

kaliatech avatar Jun 01 '15 20:06 kaliatech

@kaliatech - RE: dateWindow...that's sort of the whole problem. I don't see a clean way with the dygraphs api to accurately maintain the dateWindow when live loading, and zooming and panning with the rangeSelector.

mg1075 avatar Jun 02 '15 00:06 mg1075

is there any work around for this issue?

paresh-2016 avatar Dec 08 '16 10:12 paresh-2016

screen shot 2018-02-02 at 10 13 50 am For my solution I got it to work but I had to **remove right range selector** .

  • In options use draw callback to find the most recent date.
  • In zoom callback find the most recent range and set zoom to true
     options['drawCallback'] = (a, b) => {
      this.latest = a.file_[a.file_-length - 1][0];
      this.latest = new Date (this.latest).getTime();
    };
    options['showRangeSelector'] = this.selectRange;
    options['zoomCallback'] = (minDate, maxDate, yRanges) => {
      this.zoom = true;
      this.range = Math.abs(maxDate - minDate);

    }; 

When calling update graph function

  • find earliest by using range and subtracting by the last datapoint date
  • Update dateWindow
  if (this.zoom) {
          this.earliest = this.latest - this.range;
          this.dateWindow = [this.earliest, this.latest];
          options['dateWindow'] = this.dateWindow;
        }
        this.graph.updateOptions(options);

And also removed the right slider

  • this.chart is ElementRef from angular
const elemtArry = this.chart.nativeElement.querySelectorAll('.dygraph-rangesel-zoomhandle');
    if (elemtArry.length > 0) {
      const el = elemtArry[1];
      el.remove();
    }

AntonisFK avatar Feb 02 '18 18:02 AntonisFK

Unfortunately, maintaining a view window outside of Dygraphs leads to a different issue.

If you maintain a view window outside of Dygraphs and utilize a dynamically updating graph, the Range Selector's right handle eventually drifts outside the bounds.

Once there are no more data points, it looks like this (the handle on the left side is actually the right handle):

range_problem2

However, I did find a work-around.

In the Range Selector code, there is a method rangeSelector.prototype.placeZoomHandles_(), which defines the right handle's position as a percentage, with the line:

var rightPercent = Math.max(0, (xExtremes[1] - xWindowLimits[1])/xRange);

I overwrote the method, adding the following lines immediately after the definition of rightPercent

  if(rightPercent > 1) {
    rightPercent = 1
  }

This fixes my problem.

I know it's not explicitly related to the issue mentioned above, but it's still a dynamic graph + Range Selector problem, and it seemed overkill to make a brand new issue.

I'm using Dygraphs 1.1.1 (in a legacy project that can't upgrade to 2.0), but the code for the method rangeSelector.prototype.placeZoomHandles_() looks identical in both releases.

I hope this is useful to somebody...

ghost avatar Jun 21 '18 19:06 ghost