我正在将香草D3水平条形图转换为React D3水平条形图。我可以通过React渲染条形图,但是有一些问题:
matrix[x1]
)以便它们
不要堆叠在一起? - > 已解决,请参阅下文 matrix[x0]
)? - > 已解决,请参阅下文 我首先提供工作香草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}];
Vanilla 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; });
React Components
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}
/>
);
}
});
答案 0 :(得分:0)
我能够通过Google Foo对我所需的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} />
);
}
});