React-vis: Responsive graphs (question)

Created on 5 Feb 2017  ·  19Comments  ·  Source: uber/react-vis

What would be the preferred/best practice way to make the graphs dynamic in width/height for a responsive design?

docs

Most helpful comment

there's also the makeWidthFlexible function.

import {
  makeWidthFlexible,
  XYPlot
} from 'react-vis';

const FlexibleXYPlot = makeWidthFlexible(XYPlot); 

in the above FlexibleXYPlot behaves exactly like XYPlot but no width needs be passed. Instead, it uses the size of its containing component.
makeWidthFlexible works with width, as the name implies - in our use cases it made more sense to change the width of a chart and keep height fixed.

All 19 comments

^_^

https://about.me/hanjunxiao?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=gmail_api
Hanjun Xiao
about.me/hanjunxiao
https://about.me/hanjunxiao?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=gmail_api

On Mon, Feb 6, 2017 at 6:34 AM, bytewiz notifications@github.com wrote:

What would be the preferred/best practice way to make the graphs dynamic
in width/height for a responsive design?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/uber/react-vis/issues/262, or mute the thread
https://github.com/notifications/unsubscribe-auth/ACW3y3v55WQndXWnv6y5L803CbLSDTFhks5rZk6JgaJpZM4L3p3L
.

Hey @bytewiz

This is a pretty complex question! On the ostensible top layer (how to make a visualization that simply scales well with size changes), i tend to prefer making a stateful wrapper around my chart which measures itself on window size change and then update my visualization as appropriate. I am going to work on adding an example of this technique to one of the examples.

Beyond that there are some interesting ledgibility questions about how to make a visualization that scales well with pixel and data density. Check out this demo http://nrabinowitz.github.io/rdv/, for some cool thoughts on the matter. (also, I am in the process of re-producing that example in react-vis, checkout this PR https://github.com/uber/react-vis/pull/253).

If this isn't enough, can you tell me more about your use case? Maybe I can point you in the right direction?

@mcnuttandrew looks like what I need :) I have currently done it somewhat the same way as you proposed by programmatically calculate screensize and then "shrink" or "scale up" the graph by that calculation.

though I thought there might be a better way, and true I see that it becomes a problem when scaling down and still display the data points.

Thanks 👍

Thank you, All!

https://about.me/hanjunxiao?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=gmail_api
Hanjun Xiao
about.me/hanjunxiao
https://about.me/hanjunxiao?promo=email_sig&utm_source=product&utm_medium=email_sig&utm_campaign=gmail_api

On Tue, Feb 7, 2017 at 7:19 AM, bytewiz notifications@github.com wrote:

@mcnuttandrew https://github.com/mcnuttandrew looks like what I need :)
I have currently done it somewhat the same way as you proposed by
programmatically calculate screensize and then "shrink" or "scale up" the
graph by that calculation.

though I thought there might be a better way, and true I see that it
becomes a problem when scaling down and still display the data points.

Thanks 👍


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/uber/react-vis/issues/262#issuecomment-277846556, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACW3y5IuY0A3-N6M5_oYBuCNGE9ZQxp3ks5rZ6pxgaJpZM4L3p3L
.

Another option is svg's viewBox attribute, which allows your entire graphic to scale independently of the coordinate system. This is easy to use and works great for many things but has the downside of scaling any <text> elements in addition to scaling the graphic, which is usually not what you want.

CSS-Tricks has a good article discussing the pros and cons of several different solutions, but as @mcnuttandrew pointed out the easiest solution in React is often just to wrap a higher-order component and treat any corner-cases of your design as responsive breakpoints in JS.

there's also the makeWidthFlexible function.

import {
  makeWidthFlexible,
  XYPlot
} from 'react-vis';

const FlexibleXYPlot = makeWidthFlexible(XYPlot); 

in the above FlexibleXYPlot behaves exactly like XYPlot but no width needs be passed. Instead, it uses the size of its containing component.
makeWidthFlexible works with width, as the name implies - in our use cases it made more sense to change the width of a chart and keep height fixed.

I've just implemented the makeWidthFlexible HOC, and it took me a little while to work out how to use it correctly. For anybody else wondering, the trick is to have your plot component accept a prop named width and pass this on to the XYPlot. You also need to explicitly declare width as a propType on your base component, otherwise propTypes validation will fail (see https://github.com/uber/react-vis/blob/master/src/make-vis-flexible.js#L97).

Example:

const Plot = ({ width, measurements }) =>
    <XYPlot
      height={180}
      width={width}>
      <VerticalGridLines />
      <HorizontalGridLines />
      <XAxis />
      <YAxis />
      <LineSeries data={measurements} />
    </XYPlot>

Plot.propTypes = { width: React.PropTypes.number, measurements: React.PropTypes.array }
Plot.displayName = 'TimeSeriesLineChartPlot'
const FlexibleXYPlot = makeWidthFlexible(Plot)

export default class PlotComponentExample extends React.Component {
  render () {
    const { measurements } = this.props
    return (
      <FlexibleXYPlot measurements={measurements} />
    )
  }
}

Edit: err, might not want to recreate the Plot component in each render though. Fixed example.

Is there a plan to also expose "makeHeightFlexible" too? I'm try to use a HorizontalBarSeries chart to function as a vertical indexing sidebar, and found it would be useful to auto-determine its height.

This is great! When you resize the screen, the experience is a little choppy/bouncy...making it nice/smooth would be excellent..thank you!

Hey @julesbond007 can you say more about what you are seeing? Also, would you mind opening a new ticket about it?

Hey all,

Now that flexible plots are exposed at the top level of the library (http://uber.github.io/react-vis/#/documentation/api-reference/flexible-plots) I think we can close this issue. Discussion can continue under fold, or issue can be re-opened if folks disagree.

How about responsive Stankey Diagram?

I think it's also pending the radial chart:
https://github.com/uber/react-vis/issues/620

I've also tried with "ranking" chart (XYPlot with HorizontalBarSeries) and it doesn't seems to work. I've used makeVisFlexible, makeWidthFlexible and same result.

Before  class declaration:
const FlexibleXYPlot = makeVisFlexible(XYPlot);

Render method:
render() {
        let data = this.props.data ? _.orderBy(this.props.data, 'x', ['asc']) : this.props.data;

        data = (this.sort === 'desc') ? data.slice(0 - this.top) : data.slice(0, this.top);

        const ppp = responsiveUtilsService.getPPP(this.innerWidth, this.innerHeight, data, 'HEIGHT');
        this.featuresToRender = responsiveUtilsService.filterFeatures(BARCHART_FEATURES, ppp);
        this.xRange = [0, this.innerWidth];
        this.yRange = this.sort === 'asc' ? [0, this.innerHeight] : [this.innerHeight, 0];

        return (
            <FlexibleXYPlot
                yType="ordinal"
                xType="linear"
                margin={this.margin}
                width={this.width}
                height={this.height}
            >
                {this.featuresToRender.xaxis && <XAxis orientation="top"/>}
                {this.featuresToRender.yaxis && <YAxis />}
                {this.featuresToRender.bars && (
                    <HorizontalBarSeries
                        colorType="literal"
                        xRange={this.xRange}
                        yRange={this.yRange}
                        data={data} />
                )}
            </FlexibleXYPlot>
        );
    }

Hey all,

Now that flexible plots are exposed at the top level of the library (http://uber.github.io/react-vis/#/documentation/api-reference/flexible-plots) I think we can close this issue. Discussion can continue under fold, or issue can be re-opened if folks disagree.

I think the link quoted has been updated since then, the new link is a great help: https://uber.github.io/react-vis/documentation/api-reference/flexible-plots

@wzup

to make a react-vis sankey responsive (horizontally and vertically) use the makeVisFlexible() helper as explained here: https://uber.github.io/react-vis/documentation/api-reference/flexible-plots

little code example:

const FlexibleSankey = makeVisFlexible(Sankey);
   return (
        <FlexibleSankey
          nodes={nodes}
          links={links}
          nodePadding={20}
          align='left'
          layout={500}
        />
  )

Where is the documentation for this?
I don't understand the reason to pass width props into the width property to make flexible.
I just use

  const FlexibleGraph = makeVisFlexible(XYPlot);
  return (
    <FlexibleGraph height={300}>
      <VerticalGridLines />
      <HorizontalGridLines />
      <XAxis />
      <YAxis />
      <AreaSeries
        className="area-series-example"
        curve="curveNatural"
        data={data}
      />
    </FlexibleGraph>
  );

I'm doing this:

  componentDidMount() { //add listener to do thing
    this.updateWindowDimensions();
    window.addEventListener('resize', this.updateWindowDimensions);
  }

  componentWillUnmount() { //remove event listener after done doing thing 
    window.removeEventListener('resize', this.updateWindowDimensions);
  }

  updateWindowDimensions = () => {
    this.setState({ width: window.innerWidth });
  };

// then in render() (I'm using Sunburst from react-vis):
<Sunburst
          height={this.state.width / 4}
          width={this.state.width / 4}
/>
// using width for both dimensions because this component is a circle.

hope it helps.

It looks like FlexibleWidthXYPlot, FlexibleHeightXYPlot, and FlexibleXYPlot have been added (probably since this issue was active) in case this is useful for anyone else! https://uber.github.io/react-vis/documentation/api-reference/flexible-plots

Was this page helpful?
0 / 5 - 0 ratings