簡體   English   中英

使用 d3 和 React 的散點圖

[英]Scatter plot using d3 with React

我正在嘗試使用 d3 和 React 創建散點圖。 可用的示例並不多,但我發現很有用。 所以我的代碼如下:

class Axis extends React.Component {
    constructor(props) {
        super(props);
    }

    componentDidUpdate() {
        this.renderAxis();
    }

    componentDidMount() {
        this.renderAxis();
    }

    renderAxis() {
        const node = ReactDOM.findDOMNode(this);
        d3.select(node).call(this.props.axis);
    }

    render() {
        const translate = 'translate(0,'+(this.props.h)+')';

        return (
            <g className='axis' transform={this.props.axisType == 'x' ? translate : "" }>
            </g>
        );
    }
}


Axis.propTypes = {
    h: React.PropTypes.number,
    axis: React.PropTypes.func,
    axisType: React.PropTypes.oneOf(['x', 'y'])
};

class Points extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {

        const _self = this;
        const circles = _self.props.data.map((d, i) => {
            return (
                <circle className="dot" r="3.5" cx={_self.props.x(d)} cy={_self.props.y(d)} key={i} fill="red"/>
            );
        });
        return (
            <g>{circles}</g>
        );
    }
}

Points.propTypes = {
    data: React.PropTypes.array,
    x: React.PropTypes.func,
    y: React.PropTypes.func
}

export default class PlotBlock extends React.Component {
  constructor(props) {
        super(props);
    this.state = {
        csvData: ''
    };
  }

componentWillMount() {
    let inputData;

    inputData = [{"Name":"A1_P1","Category":"A01","Score 1":"2.3","Score 2":"2.4","Score 3":"4.1","Average score":"2.4"},{"Name":"A2_P1","Category":"A02","Score 1":"1.4","Score 2":"1.5","Score 3":"2.4","Average score":"1.5"},{"Name":"A3_P1","Category":"A03","Score 1":"0.9","Score 2":"0.9","Score 3":"0.9","Average score":"0.9"},{"Name":"A4_P1","Category":"B01","Score 1":"1.5","Score 2":"1.5","Score 3":"1","Average score":"1.5"},{"Name":"A5_P1","Category":"B02","Score 1":"1.2","Score 2":"1.2","Score 3":"1.4","Average score":"1.2"},{"Name":"A6_P1","Category":"B03","Score 1":"1","Score 2":"1","Score 3":"1.1","Average score":"1"},{"Name":"A7_P1","Category":"C01","Score 1":"1.6","Score 2":"1.2","Score 3":"1","Average score":"1.2"},{"Name":"A8_P1","Category":"C02","Score 1":"1.2","Score 2":"1.2","Score 3":"0.9","Average score":"1.2"},{"Name":"A9_P1","Category":"C03","Score 1":"1.1","Score 2":"1.1","Score 3":"1","Average score":"1.1"},{"Name":"A10_P1","Category":"D01","Score 1":"1.5","Score 2":"1.6","Score 3":"1.1","Average score":"1.5"}];

    this.setState({ csvData: inputData });

}

  render() {
    const margin = {top: 20, right: 20, bottom: 30, left: 50};
    const width = 720 - margin.left - margin.right;
    const height = 200 - margin.top - margin.bottom;

    const svg = d3.select('body').append('svg')
                  .attr('width', width + margin.left + margin.right)
                  .attr('height', height + margin.top + margin.bottom + 200)
                  .append('g')
                  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    const x = (d) => d['Category'];
    const xScale = d3.scalePoint()
                     .range([0, width]);
    const xMap = (d) => {
      return xScale(x(d));
    };
    const xAxis = d3.axisBottom(xScale);

    const y = (d) => d['Score'];
    const yScale = d3.scaleLinear()
                     .range([height, 0]);
    const yMap = (d) => {;
      return yScale(y(d));
    };
    const yAxis = d3.axisLeft(yScale);

    const svgContainerWidth = width + margin.left + margin.right;
    const svgContainerHeight = height + margin.top + margin.bottom + 200;
    const innerContainer = 'translate(' + margin.left + ',' + margin.top + ')';


    if (this.state.csvData) {
        return (
            <div className='plot-block'>
                <svg width={svgContainerWidth} height={svgContainerHeight}>
                    <g transform={innerContainer}>
                      <Axis h={height} axis={xAxis} axisType="x" />
                      <Axis h={height} axis={yAxis} axisType="y" />
                      <Points data={this.state.csvData} x={xMap} y={yMap} />
                    </g>
                </svg>
            </div>
        );
    }
    return null;
  }
}

該圖如下所示:

在此處輸入圖片說明

最大的問題是點的 'cx' 屬性根本沒有出現,而且 'cy' 值似乎也有誤。 我知道是因為我僅使用 d3 和. 特別是,當調用xMapyMap ,即使函數和輸入參數似乎與僅使用 d3 繪圖時相同,值也都是錯誤的。 我真的很困惑,沒有真正好的 React + d3 集成示例。 請幫忙。

我不是 React 用戶,但關於你代碼的 D3 部分,我相信它缺少兩個尺度的域。

他們應該是:

const yScale = d3.scaleLinear()
    .domain([0, d3.max(data, y)])
    .range([height, 0]);

const xScale = d3.scalePoint()
    .domain(data.map((d) => d["Category"]))
    .range([0, width]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM