I’m doing a project to learn d3 visualization and I’m stack recs aren’t appearing. Could you help me?
I tried to put a simple array for data and it worked, I could only flip y, but with this JSON data. nothing works
https://codepen.io/DeanWinchester88/pen/XWgjjeW
let dataSet; let data; function readTextFile(file, callback) { var rawFile = new XMLHttpRequest(); rawFile.overrideMimeType("application/json"); rawFile.open("GET", file, true); rawFile.onreadystatechange = function() { if (rawFile.readyState === 4 && rawFile.status == "200") { callback(rawFile.responseText); } } rawFile.send(null); } //usage: readTextFile("https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json", function(text){ data = JSON.parse(text); dataSet = data["data"] console.log(dataSet); }); const w = 700; const h = 500; const svg = d3.select("body") .append("svg") .attr("width",w) .attr("heigth",h) .attr("style", "outline: thin solid red;"); svg.selectAll("rect") .data(dataSet) .enter() .append("rect") .attr("x", (d,i) => d[1][i]+ 10) .attr("y", (d, i) => 0 ) .attr("width", 25) .attr("height", (d, i) => d[1] /2 ) .attr("fill", "navy") .attr("class", "bar") .append("title") .text((d) => d) svg.selectAll("text") .data(dataSet) .enter() .append("text") .text((d) => d) .attr("x", (d, i) => i * 30 +10) .attr("y", (d, i) => 15)
Advertisement
Answer
The issue is that XMLHttpRequest
is asynchronous and you are defining the d3 logic outside of the callback passed to readTextFile
. The easiest solution would be to include the d3 logic inside of the callback:
readTextFile("https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json", function(text){ data = JSON.parse(text); dataSet = data["data"] console.log(dataSet); // Add d3 logic here const w = 700; const h = 500; const svg = d3.select("body") .append("svg") .attr("width",w) .attr("heigth",h) .attr("style", "outline: thin solid red;"); svg.selectAll("rect") .data(dataSet) .enter() .append("rect") // Changed this line to remove the [i] .attr("x", (d,i) => d[1] + 10) .attr("y", (d, i) => 0 ) .attr("width", 25) .attr("height", (d, i) => d[1] /2 ) .attr("fill", "navy") .attr("class", "bar") .append("title") .text((d) => d) svg.selectAll("text") .data(dataSet) .enter() .append("text") .text((d) => d) .attr("x", (d, i) => i * 30 +10) .attr("y", (d, i) => 15) });
To avoid callback you could wrap the response to readTextFile
in a Promise
and then use async/await
to dataSet = await readTextFile(...)
.