Skip to content
Advertisement

How can I make rects from JSON?

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(...).

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement