How to run Mike Bostock's D3 examples?

2020-06-04 13:19发布

问题:

I've been trying to run Mike Bostock's See-Through Globe example, but the references to his json files are incorrect if you try to reproduce it locally.

The issue comes from this line of code:

d3.json("/mbostock/raw/4090846/world-110m.json", function(error, topo) {
      var land = topojson.feature(topo, topo.objects.land),
          grid = graticule();
});

I've followed this example: d3: us states in topojson format filesize is way too large

and tried to change the url to these variations to better reference those files for an external user;

"https://raw.github.com/mbostock/topojson/master/examples/world-110m.json"
"https://render.github.com/mbostock/topojson/master/examples/world-110m.json"
"http://bl.ocks.org/mbostock/raw/4090846/world-110m.json"

but I'm never allowed access. Any idea on how to correctly reference the json file?

I've tried some if his other examples as well, and have run into the same issue every time. Has anyone else had any success reproducing the examples?

Issue reproduced in a fiddle: http://jsfiddle.net/agconti/wBfLd/

Link to gallery example

Link to github gist

回答1:

You can't access the remote json files because of same origin policy. And you won't be able to retrieve a JSON object using the file: protocol. Unless you want to perform surgery on the code by embedding the JSON directly, you're going to have to run a local server.

An easy way to run a local web server is execute:

python -m SimpleHTTPServer 8888 &

from the "root" directory of your site and then access it via http://localhost:8888



回答2:

You can access the data directly here: http://bl.ocks.org/mbostock/raw/4090846/world-110m.json

To make it work, you'll need to create a new variable in your script and assign the json to it directly.

Code from the fiddle you provided:

var topo = // Paste data from provided link here. It will be one big object literal.

var width = 960,
    height = 960,
    speed = -1e-2,
    start = Date.now();

var sphere = {type: "Sphere"};

var projection = d3.geo.orthographic()
    .scale(width / 2.1)
    .translate([width / 2, height / 2])
    .precision(.5);

var graticule = d3.geo.graticule();

var canvas = d3.select("body").append("canvas")
    .attr("width", width)
    .attr("height", height);

var context = canvas.node().getContext("2d");

var path = d3.geo.path()
    .projection(projection)
    .context(context);

// d3.json("https://render.github.com/mbostock/topojson/master/examples/world-110m.json", function(error, topo) {
  var land = topojson.feature(topo, topo.objects.land), // topo var is now provided by pasted-in data instead of fetched json.
      grid = graticule();

  d3.timer(function() {
    context.clearRect(0, 0, width, height);

    projection.rotate([speed * (Date.now() - start), -15]).clipAngle(90);

    context.beginPath();
    path(sphere);
    context.lineWidth = 3;
    context.strokeStyle = "#000";
    context.stroke();
    context.fillStyle = "#fff";
    context.fill();

    projection.clipAngle(180);

    context.beginPath();
    path(land);
    context.fillStyle = "#dadac4";
    context.fill();

    context.beginPath();
    path(grid);
    context.lineWidth = .5;
    context.strokeStyle = "rgba(119,119,119,.5)";
    context.stroke();

    projection.clipAngle(90);

    context.beginPath();
    path(land);
    context.fillStyle = "#737368";
    context.fill();
    context.lineWidth = .5;
    context.strokeStyle = "#000";
    context.stroke();
  });
// });

d3.select(self.frameElement).style("height", height + "px");

I would have modified the fiddle directly, but the json data file is large enough that jsfiddle chokes when I try to paste it in.

Hope this helps.