2016-07-13 3 views
0

바닐라 D3 가로 막대 차트를 React D3 가로 막 대형 차트로 변환하는 중입니다. 나는 바 통해 반작용 렌더링 할 수 있지만, 몇 가지 문제가 있습니다 :D3 막대 차트를 React D3 막대 차트로 변환

  1. 하는 방법 (폭 = matrix[x1]는 곳)가 서로에 쌓아 두지 않는 그래서 내가 막대 구성 요소를 확산합니까? ->해결됨, 아래 참조
  2. 세트 1 위에 두 번째 막대 구성 요소 (너비 = matrix[x0])를 렌더링하려면 어떻게해야합니까? ->해결, 아래 참조
  3. 막대 구성 요소에 전환을 어떻게 추가합니까?

나는 작업 바닐라 D3을 먼저 제공하고 유사 작동하는 반응 D3를 제공한다.

데이터 :

var matrix = [{y:0, x0:221, x1:2054}, 
{y:1, x0:581, x1:1891}, 
{y:2, x0:2485, x1:5128}, 
{y:3, x0:135, x1:8849}, 
{y:4, x0:31, x1:242}]; 

바닐라 D3

// Constants 
var width = 450, 
    barHeight = 20, 
    height = 300, 
    delay = 500, 
    duration = 750; 

// Type Chart 
var chart = d3.select('.typeBarChart') 
    .attr('width', width) 
    .attr('height', barHeight*matrix.length); 

// X-axis 
var maxCrime = d3.max(matrix, (d) => { 
    return d.x1; 
}); 

var x = d3.scale.linear() 
    .domain([0, maxCrime+50]) 
    .range([0, width]); 

var bar = chart.selectAll("g") 
    .data(matrix) 
    .enter() 
    .append("g") 
    .attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; }); 

bar.append("rect") 
    .attr("fill","steelblue") 
    .attr("width", 0) 
    .attr("height", barHeight - 1) 
    .transition() 
    .delay(delay) 
    .duration(duration) 
    .ease("bounce") 
    .attr("width", function(d) { return x(d.x1); }) 
    .attr("height", barHeight - 1); 

bar.append("rect") 
    .attr("fill","#E6550D") 
    .attr("width", 0) 
    .attr("height", barHeight - 1) 
    .transition() 
    .delay(delay) 
    .duration(duration) 
    .ease("bounce") 
    .attr("width", function(d) { return x(d.x0); }) 
    .attr("height", barHeight - 1); 

bar.append("text") 
    .transition() 
    .delay(delay+duration) 
    .attr("x", function(d) { 
     if (d.x1 < 1000) { 
     return x(d.x1) + 20; 
     } else { 
     return x(d.x1) - 3; 
     } 
    }) 
    .attr("y", barHeight/2) 
    .attr("dy", ".35em") 
    .text(function(d) { return d.x1; }); 

는 구성 요소

const BarChart = React.createClass({ 
    render() { 
    let { width, height, matrix } = this.props; // matrix data passed in from container component 

    let maxCrime = d3.max(matrix, (d) => {return d.x1}); 

    let xScale = d3.scale.linear() 
     .domain([0, maxCrime+50]) 
     .range([0, width]); 

    return (
     <div> 
     <h3>Rendering BarChart with React</h3> 
     <svg 
      width={width} 
      height={height} > 
      <DataSeries 
       xScale={xScale} 
       matrix={matrix} /> 
     </svg> 
     </div> 
    ); 
    } 
}); 

const DataSeries = React.createClass({ 
    propTypes: { 
    barHeight:   React.PropTypes.number, 
    colors:    React.PropTypes.array, 
    matrix:    React.PropTypes.array, 
    xScale:    React.PropTypes.func 
    }, 

    getDefaultProps() { 
    return { 
     barHeight:   20, 
     matrix:    [], 
     colors:    [ 
          '#b2182b', 
          '#ef8a62', 
          '#fddbc7', 
          '#d1e5f0', 
          '#67a9cf', 
          '#2166ac' 
          ] 
    }; 
    }, 

    render() { 
    let { barHeight, matrix, colors, xScale } = this.props; 
    let bars = matrix.map((datum, index) => { 
     return (
      <Bar 
      key={index} 
      width={xScale(datum.x1)} 
      height={barHeight-1} 
      fill={colors[index]} 
      /> 
     ); 
     }); 

    return (
     <g>{bars}</g> 
    ); 
    }  
}); 

const Bar = React.createClass({ 
    propTypes: { 
    key:    React.PropTypes.number, 
    width:    React.PropTypes.number, 
    height:    React.PropTypes.number, 
    colors:    React.PropTypes.array, 
    matrix:    React.PropTypes.array, 
    xScale:    React.PropTypes.func 
    }, 

    getDefaultProps() { 
    return { 
     matrix:    [], 
    }; 
    }, 

    render() { 
    let { width, height, fill } = this.props; 

    return (
     <rect 
     width={width} 
     height={height} 
     fill={fill} 
     /> 
    ); 
    } 
}); 
+2

이제 React로 요소를 만들었으므로 d3 전환을 사용할 수 없습니다. 전환에 도움이되는 다양한 React 구성 요소/라이브러리가 있거나 자신의 기술을 발명 할 수 있습니다. 그래서 자유로운 질문입니다. – meetamit

답변

0

가 나는 일부 Google 푸에 필요한 무엇의 90 %를 삼각 측량 할 수 있었다 반응한다. 여전히 누락 된 유일한 부분은 전환입니다. 다른 사람보다 먼저 해결할 수 있다면 수정 사항을 제출할 것입니다.

export const BarChart = React.createClass({ 

    propTypes: { 
    width: React.PropTypes.number, 
    height: React.PropTypes.number, 
    data: React.PropTypes.array.isRequired 
    }, 

    getDefaultProps() { 
    return { 
     width: 450, 
     height: 300 
    }; 
    }, 

    structureData(districtNumber) { 
    let { data, districtInfo } = this.props; 

    if (districtNumber) { 
     data = data.filter((glob) => { 
     return glob.district == districtNumber; 
     }); 
    } 

    const nestedData = d3.nest() 
     .key(function(d) { 
     return d.type; 
     }) 
     .rollup(function (v) { 
     return d3.sum(v, function(d) {return parseInt(d.count);}); 
     }) 
     .entries(data) 
     .sort((a, b) => { 
     var nameA = a.key.toLowerCase(), nameB = b.key.toLowerCase(); 
     if (nameA < nameB) //sort string ascending 
      return -1; 
     if (nameA > nameB) 
      return 1; 
     return 0; 
     }); 

    return nestedData; 
    }, 

    matrixData(total, district) { 
    let matrix = []; 

    for (var i=0; i<total.length; i++) { 
     var obj = {}; 
     obj['y'] = i; 
     obj['x0'] = district[i].values; 
     obj['x1'] = total[i].values; 
     matrix.push(obj); 
    } 

    return matrix; 

    }, 

    render() { 
    let { width, height, districtInfo } = this.props; 
    const dataTotal = this.structureData(); 
    const dataDistrict = this.structureData(districtInfo.district_number); 

    const matrix = this.matrixData(dataTotal, dataDistrict); 

    let maxCrime = d3.max(dataTotal, (d) => {return d.values}); 

    let xScale = d3.scale.linear() 
     .domain([0, maxCrime+50]) 
     .range([0, width]); 

    return (
     <div> 
     <svg 
      width={width} 
      height={height} > 
      <DataSeries 
       xScale={xScale} 
       matrix={matrix} /> 
     </svg> 
     </div> 
    ); 
    } 
}); 

const DataSeries = React.createClass({ 
    propTypes: { 
    barHeight:   React.PropTypes.number, 
    colors:    React.PropTypes.array, 
    matrix:    React.PropTypes.array, 
    xScale:    React.PropTypes.func 
    }, 

    getDefaultProps() { 
    return { 
     barHeight:   20, 
     matrix:    [], 
     // interpolationType: 'cardinal', 
     colors:    [ 
          '#b2182b', 
          '#ef8a62', 
          '#fddbc7', 
          '#d1e5f0', 
          '#67a9cf', 
          '#2166ac' 
          ] 
    }; 
    }, 

    render() { 
    let { barHeight, matrix, colors, xScale } = this.props; 
    let barsTotal = matrix.map((datum, index) => { 

     let x = datum.x1 < 1000 ? xScale(datum.x1) + 20 : xScale(datum.x1) - 3; 

     const barSettings = { 
      datum: datum, 
      width: xScale(datum.x1), 
      height: barHeight-1, 
      fill: colors[index], 

     }; 

     const textSettings = { 
      x: x, 
      y: barHeight/2, 
      dy: ".35em", 
     }; 

     return (
      <g key={index} transform={`translate(0, ${index*barHeight})`} > 
      <Bar {...barSettings} /> 
      <text {...textSettings}>{datum.x1}</text> 
      </g> 
     ); 
     }); 

    let barsDistrict = matrix.map((datum, index) => { 

     const barSettings = { 
      key: index, 
      width: xScale(datum.x0), 
      height: barHeight-1, 
      fill: 'gray', 
      transform: `translate(0, ${index*barHeight})` 
     }; 

     return (
      <Bar {...barSettings} /> 
     ); 
     }); 

    return (
     <g> 
     <g>{barsTotal}</g> 
     <g>{barsDistrict}</g> 
     </g> 
    ); 
    } 

}); 

const Bar = React.createClass({ 
    propTypes: { 
    width:    React.PropTypes.number, 
    height:    React.PropTypes.number, 
    colors:    React.PropTypes.array, 
    matrix:    React.PropTypes.array, 
    xScale:    React.PropTypes.func 
    }, 

    getDefaultProps() { 
    return { 
     matrix:    [], 
    }; 
    }, 

    render() { 
    return (
     <rect {...this.props} /> 
    ); 
    } 
}); 
관련 문제