简体   繁体   English

在React应用程序中使D3图表具有响应性

[英]Making D3 chart Responsive in React app

I am currently trying to render plot in React using D3. 我目前正在尝试使用D3在React中渲染图。 To integrate both of them , i have used the following link: 为了整合它们,我使用了以下链接:

http://oli.me.uk/2015/09/09/d3-within-react-the-right-way/ . http://oli.me.uk/2015/09/09/d3-within-react-the-right-way/

I have also tried the solutions provided in the link for making the chart responsive: 我还尝试了链接中提供的用于使图表响应的解决方案:

Resize svg when window is resized in d3.js 在d3.js中调整窗口大小时调整SVG大小

Although it works great in standalone code upon integrating it with React it starts omitting ticks . 尽管它在与React集成时在独立代码中表现出色,但开始省略滴答声。 Working jsfiddle for the D3 alone: https://jsfiddle.net/adityap16/11edxrnq/1/ 仅适用于D3的有效jsfiddle: https ://jsfiddle.net/adityap16/11edxrnq/1/

Code of Standalone D3 : 独立D3的代码:

var data = [
{"mytime": "2015-12-01T11:10:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:15:00.000Z", "value": 67},
{"mytime": "2015-12-01T11:20:00.000Z", "value": 70},
{"mytime": "2015-12-01T11:25:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:30:00.000Z", "value": 72},
{"mytime": "2015-12-01T11:35:00.000Z", "value": 75},
{"mytime": "2015-12-01T11:40:00.000Z", "value": 71},
{"mytime": "2015-12-01T11:45:00.000Z", "value": 80}
];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;

data.forEach(function(d) {
          d.mytime = parseDate(d.mytime);
        });
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = { top: 30, right: 30, bottom: 40, left:50 },
height = 200,
width = 800;
var color =  "green";
var xaxis_param = "mytime";
var yaxis_param = "value"
var params1 =  {margin:margin,height:height,width:width, color: color, xaxis_param:xaxis_param, yaxis_param :yaxis_param};
draw_graph(data,params1);




function  draw_graph(data,params){


    //Get the margin 
    var xaxis_param = params.xaxis_param;
    var yaxis_param = params.yaxis_param;
    var color_code = params.color;
    var margin = params.margin;
    var height = params.height - margin.top - margin.bottom,
        width = params.width - margin.left - margin.right;

    var x_extent = d3.extent(data, function(d){
        return d[xaxis_param]});
    var y_extent = d3.extent(data, function(d){
        return d[yaxis_param]});

    var x_scale = d3.time.scale()
        .domain(x_extent)
        .range([0,width]);


    var y_scale = d3.scale.linear()
        .domain([0,y_extent[1]])
        .range([height,0]);



    //Line
    var lineGen = d3.svg.line()
        .x(function (d) {
            return x_scale(d[xaxis_param]);
        })
        .y(function (d) {
            return y_scale(d[yaxis_param]);
        });
    var myChart = d3.select('body')
              .append("div")
             .classed("svg-container", true)
             .append('svg')
     .attr("preserveAspectRatio", "xMinYMin meet")
   .attr("viewBox", "0 0 800 600")
   //class to make it responsive
   .classed("svg-content-responsive", true)    
                    .attr('class','my-chart')
                    .style('background', '#E7E0CB')

                    .append('g')
                    .attr('transform', 'translate('+ margin.left +', '+ margin.top +')');
            myChart
                    .append('svg:path')
                    .datum(data)
                    .attr('class', 'line')
                    .attr("d",lineGen)
                    .attr('stroke', color_code)
                    .attr('stroke-width', 1)
                    .attr('fill', 'none');


    var legend = myChart.append("g")
          .attr("class", "legend")
          .attr("transform", "translate(" + 5 + "," + (height - 25) + ")")

        legend.append("rect")
          .style("fill", color_code)
          .attr("width", 20)
          .attr("height", 20);

        legend.append("text")
          .text(yaxis_param)
          .attr("x", 25)
          .attr("y", 12);

    var vGuideScale = d3.scale.linear()
        .domain([0,y_extent[1]])
        .range([height, 0])

    var vAxis = d3.svg.axis()
        .scale(vGuideScale)
        .orient('left')
        .ticks(5)


    var hAxis = d3.svg.axis()
        .scale(x_scale)
        .orient('bottom')
        .ticks(d3.time.minute, 5);

  myChart.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(hAxis);

  myChart.append("g")
      .attr("class", "y axis")
      .call(vAxis)


}

I might need to need to setState or something upon resize, that should trigger React to re-render with the new information but being new to React , i am not able to make it work. 我可能需要设置setState或调整大小的东西,这应该触发React重新渲染新信息,但对于React来说是新手,我无法使其工作。

Edit: I am still trying to edit but the problem seems to be the ticks on x axis and y axis when you shrink the window you are able to see the ticks but not in a full screen. 编辑:我仍在尝试编辑,但问题似乎出在缩小窗口时,您在x轴和y轴上的刻度都可以看到刻度,但不能在全屏模式下查看。 Still trying to understand why? 仍在试图了解为什么?

Thanks! 谢谢!

So i was able to find the answer in one of the open issues in React on Github (react-d3 components). 因此,我能够在Github上的React(react-d3组件)中的一个未解决的问题中找到答案。 Attached is the link and a code snippet: 附件是链接和代码片段:

https://github.com/codesuki/react-d3-components/issues/9 https://github.com/codesuki/react-d3-components/issues/9

Code: 码:

let AreaGraph = React.createClass({
    mixins: [React.addons.PureRenderMixin],

    getInitialState() {
        return {
            parentWidth: 0
        }
    },

    getDefaultProps() {
        return {
            width: '100%',
            height: 300,
            margin: { left: -1, top: 10, bottom: 0, right: 1 }
        }
    },

    handleResize(e) {
        let elem = this.getDOMNode();
        let width = elem.offsetWidth;

        this.setState({
            parentWidth: width
        });
    },

    componentDidMount() {
        if(this.props.width === '100%') {
            window.addEventListener('resize', this.handleResize);
        }
        this.handleResize();
    },

    componentWillUnmount() {
        if(this.props.width === '100%') {
            window.removeEventListener('resize', this.handleResize);
        }
    },

    render() {
        let { width, height, margin, xScale, yScale, xAxis, ...props } = this.props;

        // Determine the right graph width to use if it's set to be responsive
        if(width === '100%') {
            width = this.state.parentWidth || 400;
        }

        // Set scale ranges
        xScale && xScale.range([0, width - (margin.left + margin.right)]);
        yScale && yScale.range([height - (margin.top + margin.bottom), 0]);

        return (
            <div className={"usage__cpu__graph "+props.className}>
                <AreaChart
                    ref="chart"
                    width={width}
                    height={height}
                    margin={margin} 
                    xScale={xScale}
                    yScale={yScale}
                    xAxis={xAxis}
                    {...props} 
                />
            </div>
        );
    }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM