Skip to content

autoscale axis based on visible range #5544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hp8wvvvgnj6asjm7 opened this issue Mar 11, 2021 · 5 comments
Closed

autoscale axis based on visible range #5544

hp8wvvvgnj6asjm7 opened this issue Mar 11, 2021 · 5 comments

Comments

@hp8wvvvgnj6asjm7
Copy link

hp8wvvvgnj6asjm7 commented Mar 11, 2021

I'm going to make a compilation of people who asked for this feature over the years:

Is there any known workaround to get this functionality?

#1876

and don't even bother on using the rangeslider on real time data. It's just broken.
Would be nice to warn people before they start building their software around this.

@hp8wvvvgnj6asjm7 hp8wvvvgnj6asjm7 changed the title autoscale based on y axis autoscale axis based on visible range Mar 11, 2021
@hp8wvvvgnj6asjm7
Copy link
Author

how much sponsoring is needed for this feature?

@nicolaskruchten
Copy link
Contributor

See #1876 for details basically.

@wallneradam
Copy link

I've created a workaround for this. Maybe not as good as it could be.

  • It is scaled after the movement is ready
  • It can only scale y values, but works well with subplots too

It works great in my project, maybe somebody found it useful:

    /**
     * AutoScale
     */
    var relayout_semaphore = false,
        vi_min = null, vi_max = null;
    chart.on('plotly_relayout', function () {
        // Prevent infinite loop of relayout
        if (relayout_semaphore) return;
        relayout_semaphore = true;

        // We need to use this inner property, because e.g. after screen resize no xrange is in event properties
        // If it not allowed in your project you can use event properties and disable responsive in plot settings!
        var xrange = chart._fullLayout.xaxis.range;

        var xr_min = xrange[0],
            xr_max = xrange[1],
            layout_change = {};

        if (chart.data) {
            var trace = chart.data[0];  // 1st trace
            vi_min = null;
            vi_max = null;
            if (trace.x) {
                // Convert range values to date if x value is date
                var x = trace.x[0];
                if (x instanceof Date) {
                    xr_min = new Date(xr_min);
                    xr_max = new Date(xr_max);
                }
                // Get visible indexes
                for (var xi = 0; xi < trace.x.length; xi++) {
                    x = trace.x[xi];
                    if (!vi_min) {
                        if (x >= xr_min) vi_min = Math.max(0, xi - 1);  // Need 1 before the range
                    } else {
                        if (x <= xr_max) vi_max = Math.min(xi + 1, trace.x.length); // Need 1 after
                        else break
                    }
                }
                // Get min-max y values between indexes
                for (var t = 0; t < chart.data.length; t++) {
                    var y_min = Number.MAX_VALUE,
                        y_max = -Number.MAX_VALUE;
                    trace = chart.data[t];
                    for (var yi = vi_min; yi <= vi_max; yi++) {
                        var y = trace.y[yi];
                        if (y < y_min) y_min = y;
                        if (y > y_max) y_max = y;
                    }
                    layout_change['yaxis' + (t > 0 ? t + 1 : '') + '.range'] = [y_min, y_max];
                }
            }
        }

        if (layout_change) {
            Plotly.relayout(chart, layout_change);
            setTimeout(function () {
                relayout_semaphore = false;
            }, 0);
        }
    });

@nicolaskruchten
Copy link
Contributor

This looks great! If you want to submit this as a PR to the main library, we'd be happy to help you integrate it :)

@gitterspec
Copy link

@wallneradam Any way for me to integrate this code into a Dash graph? Desperately need this functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants