我正在尝试使用带有React的d3创建散点图。可用的例子不多,但我发现this很有用。所以我的代码如下:
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和。特别是,当调用xMap
和yMap
时,即使函数和输入参数看起来与仅使用d3绘图时相同,但值都是错误的。我真的很困惑,没有React + d3集成的真正好例子。请帮忙。
答案 0 :(得分:1)
我不是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]);