2016-07-13 120 views
0

我正在將香草D3水平條形圖轉換爲React D3水平條形圖。我可以渲染條通過反應,但有幾個問題:將D3條形圖轉換爲React D3條形圖

  1. 如何傳播欄組件(其中width = matrix[x1]),使他們 時不相互疊加麼? - >已解決,請參閱下面的內容
  2. 如何渲染集合1頂部的第二組小節組件(其中width = matrix[x0])? - >已解決,請參閱下面的內容
  3. 如何向條形組件添加轉換?

我首先提供了工作香草D3和準工作React 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

我能夠三角測量什麼,我需要一些谷歌美孚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} /> 
    ); 
    } 
});