Интерактивная картограмма почтового индекса d3 — штат Вашингтон

Как следует из названия, я пытаюсь сделать интерактивную хороплет, используя d3. Я нашел интересный пример, который пытаюсь воспроизвести в другом месте. Конкретно, я пытаюсь изобразить штат Вашингтон на уровне почтового индекса.

Я добавил код, который у меня есть на данный момент, который потенциально может быть отредактирован, он основан на этом пример вот живой демонстрация, показывающая окончательный результат.

Это работает для штата Калифорния, однако при смене почтового индекса штата (на штат Вашингтон) сюжет не работает. Также нет явных ошибок. Ошибка могла быть в различиях в топожсоне.

Это калифорнийский топожсон, здесь Вашингтонская версия.

Ниже приведены первые значения, красиво напечатанные для каждого топографа.

California topojson:
    {
      "type": "Topology",
      "objects": {
        "zip": {
          "type": "GeometryCollection",
          "crs": {
            "type": "name",
            "properties": {
              "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
            }
          },
          "geometries": [
            {
              "type": "Polygon",
              "properties": {
                "zipcode": 94601
              },
              "arcs": [
                [
                  0,
                  1,
                  2,
                  3,
                  4,
                  5
                ]
              ]
            }

Вашингтон топожсон:

{
  "type": "Topology",
  "objects": {
    "tl_2010_53_zcta510": {
      "type": "GeometryCollection",
      "crs": {
        "type": "name",
        "properties": {
          "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
        }
      },
      "geometries": [
        {
          "type": "Polygon",
          "properties": {
            "zipcode": "98822"
          },
          "arcs": [
            [
              0,
              1,
              2,
              3
            ],
            [
              4
            ]
          ]
        }

Ниже приведена функция main.js. Я предполагаю, что это и проверка обоих файлов topojson может помочь найти проблему. В основном меняется только файл topojson, тогда функция main.js должна отражать эти изменения.

Также «fake_data.csv» будет просто представлять серию пар zipcode:value как:

zip,values
98001,1
98002,1
98003,1
98004,2
98005,2
98006,2

main.js

    (function chart() {

  var width = 1000,
      height = 1200,
      centered;

  var rateById = d3.map();

  var quantize = d3.scale.quantize()
      .domain([0, 100000])
      .range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));

  var projection = d3.geo.albersUsa()
      .scale(6000)
      .translate([2300, 680]);

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

  var svg = d3.select("#ca-chart").append("svg")
      .attr("width", width)
      .attr("height", height);

  var tooltip = d3.select("#ca-chart").append("div")
      .attr("class", "tooltip")
      .style("opacity", 0);

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

  var g = svg.append("g");

// These are the two lines that are different from the working example
  queue()
      .defer(d3.json, "https://gist.githubusercontent.com/martinbel/e14cd6ecd565914f53af/raw/e3a3a8332c20fe3cee6d7fd2a9ac01ad43f7aaa4/WA.topojson")
      .defer(d3.csv, "fake_data.csv", function(d) { rateById.set(d.zip.toString(), +d.values); })
      .await(ready);

  function ready(error, zipcode) {
    var features = topojson.feature(zipcode, zipcode.objects.tl_2010_53_zcta510).features;

    g.append("g")
        .attr("class", "state")
      .selectAll("path")
        .data(topojson.feature(zipcode, zipcode.objects.tl_2010_53_zcta510).features)
      .enter().append("path")
        .attr("d", path)
        .attr("stroke", "#333")
        .attr("stroke-width", "1.5px")
        .attr("fill", "#fff");

    g.append("g")
        .attr("class", "zipcodes")
      .selectAll("path")
        .data(features)
      .enter().append("path")
        .attr("class", getColorClass)
        .attr("d", path)
        .on("click", clicked)
        .on("mouseover", mouseover)
        .on("mouseout", mouseout);
  }

  function getColorClass(d) {
    return quantize(rateById.get(d.properties.zipcode));
  }

  function getPopulation(d) {
    return rateById.get(getZip(d)).toString();
  }

  function getZip(d) {
    return d && d.properties ? d.properties.zipcode : null;
  }

  function mouseout(d) {
    d3.select(this)
        .style("stroke", null);

    tooltip.transition()
        .duration(250)
        .style("opacity", 0);
  }

  function mouseover(d) {
    d3.select(this.parentNode.appendChild(this))
        .style("stroke", "#F00");

    tooltip.transition()
        .duration(250)
        .style("opacity", 1);

    tooltip
        .html("<p><strong>Zipcode: " + getZip(d) + "<br>Population: "  + getPopulation(d) + "</strong></p>")
        .style("left", (d3.event.pageX + 25) + "px")
        .style("top",  (d3.event.pageY - 28) + "px");
    }

  function clicked(d) {
    var x, y, k;

    if (d && centered !== d) {
      var centroid = path.centroid(d);
      x = centroid[0];
      y = centroid[1];
      k = 8;    // control zoom depth
      centered = d;
    } else {
      x = width / 2;
      y = height / 2;
      k = 1;
      centered = null;
    }

    g.selectAll("path")
        .classed("active", centered && function(d) { return d === centered; });

    g.transition()
        .duration(750)
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
        .style("stroke-width", 1.5 / k + "px");
  }

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

}());

Файл topojson был создан следующим образом:

curl -O "ftp://ftp2.census.gov/geo/tiger/TIGER2010/ZCTA5/2010/tl_2010_53_zcta510.zip"
unzip "tl_2010_53_zcta510.zip"
ogr2ogr -f GeoJSON -s_srs crs:84 -t_srs crs:84 tl_2010_53_zcta510.geojson tl_2010_53_zcta510.shp
topojson -o tl_2010_53_zcta510.topojson --properties zipcode=ZCTA5CE10 tl_2010_53_zcta510.geojson

person marbel    schedule 07.02.2016    source источник
comment
Марбель, из твоего вопроса мне прямо не ясно, в чем твоя проблема. Можете ли вы уточнить это?   -  person tilt    schedule 07.02.2016
comment
@tilt Я добавил больше деталей в вопрос. Дайте мне знать, если это поможет понять проблему   -  person marbel    schedule 07.02.2016


Ответы (2)


Проблема в том, что вы рисуете пути за пределами активной области просмотра. Попробуйте именно это в качестве projection, и вы увидите пути.

var projection = d3.geo.albersUsa()
  // .scale(6000)
  // .translate([2300, 680]);

Вам придется отредактировать масштабирование/перевод для Вашингтона... может быть полезно сделать ваши svg width и height огромными (10000 пикселей или около того), когда вы делаете это, чтобы вы могли видеть, где заканчивается карта.

person adilapapaya    schedule 07.02.2016
comment
Разве нет лучшего способа сделать это? В идеале я бы не хотел изменять параметры вручную. - person marbel; 07.02.2016

Это решило проблему отображения карты и ее отображения без необходимости вручную изменять параметры. На самом деле хитрость заключается в использовании проекции, которая поддерживает метод .center(), а albersUsa — нет. Тогда гораздо проще разобраться с параметром масштаба.

var projection = d3.geo.mercator()
            .center([-120.574951, 47.361153])
            .scale(5000)
            .translate([(width) / 2, (height)/2]);

После этого появились другие проблемы.

person marbel    schedule 08.02.2016