Skip to content Skip to sidebar Skip to footer

D3 Bar Graph Example Not Working Locally

I am very new to D3, and wanted to see how an example would work locally. I copied and pasted the bar graph code to a local file called index.html, and also copied over the data.ts

Solution 1:

The d3.tsv method makes an AJAX request for data. On most browsers, this won't work locally due to the Same Origin Policy, which generally prohibits AJAX requests to file:/// urls.

To get an example that uses AJAX running locally, you'll need a local webserver. If you have Python, running

> python -m SimpleHTTPServer

from the command line in the directory with your files will do it.

and if you are using python 3

> python -m http.server 9000

If you prefer node.js, try http-server.

Solution 2:

As an alternative, and I was myself suggested by Lars Kotthoff when trying to work with .tsv/.csv files, you can work directly for this purpose on:

http://plnkr.co/

This enables you to work with all the .json / .tsv / .csv files you like, and share them with people for collaboration. You can do this anonymously or not, what matters is that you don't lose the then-generated HTTP address of your plunker.

One thing to pay attention to: you cannot upload directly the files in the way you would do on an FTP server, but you should instead:

  1. Click on "new file"
  2. Type the name of your .csv / .tsv / .json file as referred to in your code (including the extension)
  3. Copy and paste the code contained in this file as is.
  4. Don't forget to update the names of your .css / .js if required so the match with that of your index.html

Solution 3:

As already stated, you're most likely encountering a CORS issue with the XHR in the d3 library for an external resource to parse the JSON data.

However, here is another solution: use JSONP and Express/Node.js in conjunction with a jQuery function to initiate a client-side request for JSON, instead of using the original wrapper for d3 functions.

Had to remove the original d3.json wrapper and populate the adjacency diagrams with data from the request. Begin by cloning or downloading jsonp-d3-experiment and start the server using node server.js. Of course you need to have Node.js installed globally, beginning with Node Packaged Modules (npm). Copy your program into a subdirectory.

Put your JSON data in the jsonp-d3-experiment directory and modify server.js to route the request to your data:

// Return data from callback
server.get('/example', function(req, res)
{
  // Read the JSON data and send to JSONP response
  readJSON('example.json', function (e, json)
  {
    if (e) { throw e; }
    res.jsonp(json);
  });
});

Below is the code I modified for a co-occurrence matrix. I moved the entire script into $.getJSON and removed the d3.json function altogether.

<script>
    $.getJSON("http://localhost:8080/example?callback=?", function(result){

      miserables = result;

      var margin = {
          top: 80,
          right: 0,
          bottom: 10,
          left: 80
        },
        width = 720,
        height = 720;

      var x = d3.scale.ordinal().rangeBands([0, width]),
        z = d3.scale.linear().domain([0, 4]).clamp(true),
        c = d3.scale.category10().domain(d3.range(10));

      var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .style("margin-left", -margin.left + "px")
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");


        var matrix = [],
          nodes = miserables.nodes,
          n = nodes.length;

        // Compute index per node.
        nodes.forEach(function(node, i) {
          node.index = i;
          node.count = 0;
          matrix[i] = d3.range(n).map(function(j) {
            return {
              x: j,
              y: i,
              z: 0
            };
          });
        });

        // Convert links to matrix; count character occurrences.
        miserables.links.forEach(function(link) {
          matrix[link.source][link.target].z += link.value;
          matrix[link.target][link.source].z += link.value;
          matrix[link.source][link.source].z += link.value;
          matrix[link.target][link.target].z += link.value;
          nodes[link.source].count += link.value;
          nodes[link.target].count += link.value;
        });

        // Precompute the orders.var orders = {
          name: d3.range(n).sort(function(a, b) {
            return d3.ascending(nodes[a].name, nodes[b].name);
          }),
          count: d3.range(n).sort(function(a, b) {
            return nodes[b].count - nodes[a].count;
          }),
          group: d3.range(n).sort(function(a, b) {
            return nodes[b].group - nodes[a].group;
          })
        };

        // The default sort order.
        x.domain(orders.name);

        svg.append("rect")
          .attr("class", "background")
          .attr("width", width)
          .attr("height", height);

        var row = svg.selectAll(".row")
          .data(matrix)
          .enter().append("g")
          .attr("class", "row")
          .attr("transform", function(d, i) {
            return"translate(0," + x(i) + ")";
          })
          .each(row);

        row.append("line")
          .attr("x2", width);

        row.append("text")
          .attr("x", -6)
          .attr("y", x.rangeBand() / 2)
          .attr("dy", ".32em")
          .attr("text-anchor", "end")
          .text(function(d, i) {
            return nodes[i].name;
          });

        var column = svg.selectAll(".column")
          .data(matrix)
          .enter().append("g")
          .attr("class", "column")
          .attr("transform", function(d, i) {
            return"translate(" + x(i) + ")rotate(-90)";
          });

        column.append("line")
          .attr("x1", -width);

        column.append("text")
          .attr("x", 6)
          .attr("y", x.rangeBand() / 2)
          .attr("dy", ".32em")
          .attr("text-anchor", "start")
          .text(function(d, i) {
            return nodes[i].name;
          });

        functionrow(row) {
          var cell = d3.select(this).selectAll(".cell")
            .data(row.filter(function(d) {
              return d.z;
            }))
            .enter().append("rect")
            .attr("class", "cell")
            .attr("x", function(d) {
              returnx(d.x);
            })
            .attr("width", x.rangeBand())
            .attr("height", x.rangeBand())
            .style("fill-opacity", function(d) {
              returnz(d.z);
            })
            .style("fill", function(d) {
              return nodes[d.x].group == nodes[d.y].group ? c(nodes[d.x].group) : null;
            })
            .on("mouseover", mouseover)
            .on("mouseout", mouseout);
        }

        functionmouseover(p) {
          d3.selectAll(".row text").classed("active", function(d, i) {
            return i == p.y;
          });
          d3.selectAll(".column text").classed("active", function(d, i) {
            return i == p.x;
          });
        }

        functionmouseout() {
          d3.selectAll("text").classed("active", false);
        }

        d3.select("#order").on("change", function() {
          clearTimeout(timeout);
          order(this.value);
        });

        functionorder(value) {
          x.domain(orders[value]);

          var t = svg.transition().duration(2500);

          t.selectAll(".row")
            .delay(function(d, i) {
              returnx(i) * 4;
            })
            .attr("transform", function(d, i) {
              return"translate(0," + x(i) + ")";
            })
            .selectAll(".cell")
            .delay(function(d) {
              returnx(d.x) * 4;
            })
            .attr("x", function(d) {
              returnx(d.x);
            });

          t.selectAll(".column")
            .delay(function(d, i) {
              returnx(i) * 4;
            })
            .attr("transform", function(d, i) {
              return"translate(" + x(i) + ")rotate(-90)";
            });
        }

        var timeout = setTimeout(function() {
          order("group");
          d3.select("#order").property("selectedIndex", 2).node().focus();
        }, 5000);
      });
</script>

Notice that now the JSON data is in result, so the easiest thing to do was to assign it to miserables.

Note: jQuery is required for this solution.

Now you should be able to locally open and render all your d3 visualizations without hosting them on a server--simply open them in your browser straight from your local filesystem.

HTH!

Post a Comment for "D3 Bar Graph Example Not Working Locally"