I am achingly close to finishing a group bar chart in React using react-faux-dom package. Everything is set except for the actual rectangles. Been spinning my wheels for a few hours so I'm hoping someone can see what I'm missing. The example that I'm working from is here. My goal is to have a time scale x-axis with multi bar groups. The X and Y axes are currently rendering without issue.
Data structure currently looks like so:
[ {key: "oauths", values: [ { date: Tue Jul 26 2016 00:00:00 GMT-1000 (HST), key: "oauths", value: 3060}, { date: Tue Jul 27 2016 00:00:00 GMT-1000 (HST), key: "oauths", value: 2060}, { date: Tue Jul 28 2016 00:00:00 GMT-1000 (HST), key: "oauths", value: 3270}, ...]}, {key: "user_stats", values: [ { date: Tue Jul 26 2016 00:00:00 GMT-1000 (HST), key: "user_stats", value: 2976}, ... ]} ] The React component's render method is below. It error on the final svg.append()...
render() { const data = [ {}, {} ]; // see above // Constants const margin = {top: 30, right: 20, bottom: 30, left: 50}, width = 600 - margin.left - margin.right, height = 400 - margin.top - margin.bottom, n = this.props.dataQueryPeriod.length, // number of samples m = 2; // number of series // Parse the date / time const parseDate = d3.time.format("%Y-%m-%d").parse; // Set ranges const yScale = d3.scale.linear() .range([height, 0]); const x0 = d3.scale.ordinal() .domain(d3.range(n)) .rangeBands([0, width], .2); const x1 = d3.scale.ordinal() .domain(d3.range(m)) .rangeBands([0, x0.rangeBand()]); const xScale = d3.time.scale().range([0, width]); // Test colors var z = d3.scale.category10(); // Define axes const xAxis = d3.svg.axis() .scale(xScale) .orient("bottom") .ticks(d3.time.days); const yAxis = d3.svg.axis() .scale(yScale) .orient("left") .tickFormat(d3.format("s")); // Convert structured data to nested data const nest = d3.nest() .key(function(d) { return d.key; }) .sortKeys(d3.ascending); // Create node let node = ReactFauxDOM.createElement('svg'); let svg = d3.select(node) .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom+40) .append("g") .attr("transform", `translate(${margin.left},${margin.top})`); data.forEach(function(d) { d.date = parseDate(d.date); d.value = +d.value; }); const nestedData = nest.entries(data); console.log("nested data", nestedData); console.log("pre nest data", data); // Define axes domains xScale.domain(d3.extent(data, function(d) { return d.date; })); yScale.domain([0, d3.max(data, function(d) { return d.value; })]); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.append("g") .attr("class", "x axis") .attr("transform", `translate(0,${height})`) .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", function(d) { return "rotate(-65)"; }); svg.append("g").selectAll("g") .data(nestedData) .enter().append("g") .style("fill", function(d, i) { return z(i); }) .attr("transform", function(d, i) { return `translate(${x1(i)},0)`; }) .selectAll("rect") .data(function(d) { return d.value; }) .enter().append("rect") .attr("width", x1.rangeBand()) .attr("height", yScale) .attr("x", function(d, i) { return x0(i); }) .attr("y", function(d) { return height - yScale(d.value); }); return node.toReact(); }
If your data is starting out like the example you provided, it's already nested and d3.nest(). Assuming that the data from your example is nestedData, then your problem is that you need to bind values not value. See below:
svg.append("g").selectAll("g") .data(nestedData) .enter() .append("g") .style("fill", function(d, i) { return z(i); }) .attr("transform", function(d, i) { return `translate(${x1(i)},0)`; }) .selectAll("rect") .data(function(d) { return d.values; }) // This needs to be values .enter().append("rect") .attr("width", x1.rangeBand()) .attr("height", yScale) .attr("x", function(d, i) { return x0(i); }) .attr("y", function(d) { return height - yScale(d.value); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With