最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - D3 Bar Graph example not working locally - Stack Overflow

programmeradmin4浏览0评论

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.tsv. For some reason, absolutely nothing is showing up when I open the file on a browser! I tried changing the script src to "d3/d3.v3.min.js" because that is the folder the d3 I downloaded is in. However, this does not work either. For every example I have tried I have yet to successfully view a D3 example. Help would be appreciated!

The index.html code is as follows:

<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
fill: steelblue;
}

.x.axis path {
 display: none;
}

</style>
<body>
<script src="d3/d3.v3.min.js"></script>
<script>

var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;

var formatPercent = d3.format(".0%");

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

var y = d3.scale.linear()
   .range([height, 0]);

var xAxis = d3.svg.axis()
   .scale(x)
   .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .tickFormat(formatPercent);

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

d3.tsv("data.tsv", type, function(error, data) {
 x.domain(data.map(function(d) { return d.letter; }));
 y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

  svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

  svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
  .append("text")
  .attr("transform", "rotate(-90)")
  .attr("y", 6)
  .attr("dy", ".71em")
  .style("text-anchor", "end")
  .text("Frequency");

  svg.selectAll(".bar")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .attr("x", function(d) { return x(d.letter); })
  .attr("width", x.rangeBand())
  .attr("y", function(d) { return y(d.frequency); })
  .attr("height", function(d) { return height - y(d.frequency); });

});

function type(d) {
d.frequency = +d.frequency;
 return d;
}

</script>

and the data.tsv is in the following format: letter frequency A .08167 B .01492 C .02780 D .04253 E .12702 F .02288 G .02022 H .06094 I .06973

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.tsv. For some reason, absolutely nothing is showing up when I open the file on a browser! I tried changing the script src to "d3/d3.v3.min.js" because that is the folder the d3 I downloaded is in. However, this does not work either. For every example I have tried I have yet to successfully view a D3 example. Help would be appreciated!

The index.html code is as follows:

<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
fill: steelblue;
}

.x.axis path {
 display: none;
}

</style>
<body>
<script src="d3/d3.v3.min.js"></script>
<script>

var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;

var formatPercent = d3.format(".0%");

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);

var y = d3.scale.linear()
   .range([height, 0]);

var xAxis = d3.svg.axis()
   .scale(x)
   .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .tickFormat(formatPercent);

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

d3.tsv("data.tsv", type, function(error, data) {
 x.domain(data.map(function(d) { return d.letter; }));
 y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

  svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);

  svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
  .append("text")
  .attr("transform", "rotate(-90)")
  .attr("y", 6)
  .attr("dy", ".71em")
  .style("text-anchor", "end")
  .text("Frequency");

  svg.selectAll(".bar")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .attr("x", function(d) { return x(d.letter); })
  .attr("width", x.rangeBand())
  .attr("y", function(d) { return y(d.frequency); })
  .attr("height", function(d) { return height - y(d.frequency); });

});

function type(d) {
d.frequency = +d.frequency;
 return d;
}

</script>

and the data.tsv is in the following format: letter frequency A .08167 B .01492 C .02780 D .04253 E .12702 F .02288 G .02022 H .06094 I .06973

Share Improve this question asked Sep 24, 2013 at 3:23 redred 1771 silver badge8 bronze badges 1
  • have you looked at the console, and if you have what does it say? – user1614080 Commented Sep 24, 2013 at 4:26
Add a comment  | 

3 Answers 3

Reset to default 19

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.

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

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;
          });

        function row(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) {
              return x(d.x);
            })
            .attr("width", x.rangeBand())
            .attr("height", x.rangeBand())
            .style("fill-opacity", function(d) {
              return z(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);
        }

        function mouseover(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;
          });
        }

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

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

        function order(value) {
          x.domain(orders[value]);

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

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

          t.selectAll(".column")
            .delay(function(d, i) {
              return x(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!

发布评论

评论列表(0)

  1. 暂无评论