【发布时间】:2016-07-13 22:15:10
【问题描述】:
我正在将原版 D3 水平条形图转换为 React D3 水平条形图。我可以通过 React 渲染条形图,但是有几个问题:
- 如何展开条形组件(其中宽度 =
matrix[x1]),以便它们 不要相互堆叠? --> 已解决,见下文 - 如何在第 1 组顶部渲染第二组条形组件(其中宽度 =
matrix[x0])? --> 已解决,见下文 - 如何向条形组件添加过渡?
我首先提供工作的 vanilla 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}
/>
);
}
});
【问题讨论】:
-
现在您正在使用 React 创建元素,您将无法使用 d3 过渡。有各种 React 组件/库可以帮助转换,或者您可以发明自己的技术。所以这是一个开放式问题。
标签: javascript d3.js reactjs