10

I have implemented a scatterplot using react-plotly.js I would like the chart to re-size itself when the page layout changes. But currently, the layout of the chart doesn't change by itself. If I explicitly perform some function on the chart which forces the chart to redraw itself then only the chart width changes.

I applied useResizeHandler property and have set autosize to true. But that doesn't make any difference either.

<Plot
   useResizeHandler
   style={{ width: '100%' }}
   data={chartData}
   onClick={(data) => this.handlePlotClick(data)}
   type={'scatter'}
   layout={this.layout} />

 const layout = {
      autosize: true,
      dragmode: true,
      margin: {
        l: 5,
        r: 5,
        t: 10,
        b: 10,
        pad: 0,
        autoexpand: true
      },
      hovermode: 'closest',
      hoverlabel: {
        bgcolor: 'rgba(0,0,0,1)',
        bordercolor: 'rgba(200,200,200,1)'
      },
      height: '650',
      yaxis: {
        visible: false
      },
      xaxis: {
        autorange: false,
        showline: true,
        fixedrange: false, // true disables range selection on main graph
        rangeslider: {
          range: this.state.sliderRange,
          visible: true,
          borderwidth: 1,
          bordercolor: '#000'
        }
      }
    };
  }

enter image description here As you can see in the screenshot above, the div.svg-container has same width as the main-svg. But it still leaves white space on the right. I am unable to debug why it would behave that way. If I explicitly perform zoom on the chart that will redraw the plot then it will behave correctly. But I would like it to automatically resize when the page layout changes.

2 Answers 2

11

I was stuck on this problem too. Try window.dispatchEvent(new Event('resize')) from http://codrate.com/questions/how-can-trigger-the-window-resize-event-manually-in-javascript

I was calling resizeHandler when my chart is resized by dragging.

resizeHandler = () => {
    this.child.resizeHandler();
    window.dispatchEvent(new Event('resize'));
}

The charts always autoscales when the chart is resized, so I basically trigger the window resize when my chart size is changed. So for you, when you detect the page layout changes you can trigger the window resize.

Sign up to request clarification or add additional context in comments.

2 Comments

I seems like it hasn't been mentioned yet but there is a plotly config option called 'responsive' that can be set to true to help handle a dynamic chart size. plot.ly/javascript/responsive-fluid-layout mentions that this is 'useful for phones!' so i suspect it was made with landscape/portrait mode switching in mind. So the window's resize event seems to trigger the re-calculation of the chart dimensions.
This should be an answer. Works!
0

Here's a complete implementation with a resizable div so that a user can resize the plot to any size they want by resizing the parent div; it's using the ResizeObserver. This is slightly different than your question, but I felt like it would be useful for others searching for this question.

The plotly figure sits inside of a custom ResizableDiv component.

import _ from "lodash";
import PropTypes from "prop-types";
import React, {Component} from "react";
import ReactDOM from "react-dom";
import Plot from "react-plotly.js";

class ResizableDiv extends Component {
    constructor(props) {
        super(props);
        this.ref = React.createRef();
    }
    componentDidMount() {
        this.observer = new window.ResizeObserver(
            _.debounce(item => window.dispatchEvent(new Event("resize")), 1000)
        );
        this.observer.observe(this.ref.current);
    }
    componentWillUnmount() {
        this.observer.unobserve();
    }
    render() {
        return (
            <div style={{resize: "both", overflow: "hidden"}} ref={this.ref}>
                {this.props.children}
            </div>
        );
    }
}
ResizableDiv.propTypes = {
    children: PropTypes.element,
};

class PlotlyFigure extends Component {
    render() {
        const {data, layout} = this.props;
        return (
            <ResizableDiv>
                <Plot
                    data={data}
                    layout={layout}
                    useResizeHandler={true}
                    style={{width: "100%", height: "100%"}}
                />
            </ResizableDiv>
        );
    }
}
PlotlyFigure.propTypes = {
    data: PropTypes.array,
    layout: PropTypes.object,
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.