用于南非和各省的d3.js和dc.js的geoJSON投影

时间:2015-10-01 09:45:48

标签: d3.js geojson dc.js

我一直在努力尝试使用带有d3.js投影的dc.js来绘制南非和各省的地图。我已经用尽了我的搜索,因为大多数结果都包含了不使用dc.js时用于SVG的路径,我似乎无法找到一个合适的例子来纠正dc.js中的投影。

我似乎无法找到正在绘制的地图,而且我也不知道如何纠正我的预测。

我真的不知道自己错过了什么,任何可以提供帮助的人都会受到赞赏。

更新:我有geoJson,我已经在mapshaper中测试了它,因此geojson很好。我只是在努力进行投射。

 zaMap = zaMapString

//new array
var zaMapData = [];
    for(var p in zaMap["features"])
        {
            console.log("ndx2 province data " + zaMap["features"][p]["properties"]["name"]);
            zaMapData.push({

                province: zaMap["features"][p]["properties"]["name"],
                donation: 1000
            })
        };

//crossfilter instance
var ndx2 = crossfilter(zaMapData);

//dimensions and group for dc/d3
var provinceDim = ndx2.dimension(function(d) {console.log("province d " + d["province"]); return d["province"];});
var donationsByProvince = provinceDim.group().reduceSum(function(d) {
        return d["donation"];
        });

//geoChoroplethChart
var zaChart = dc.geoChoroplethChart("#map");

//start of chart code using d3 and dc


zaChart.dimension(provinceDim)
    .group(donationsByProvince)
    .width(1000)
    .height(330)
    .colors(["#E2F2FF", "#C4E4FF", "#9ED2FF", "#81C5FF", "#6BBAFF", "#51AEFF", "#36A2FF", "#1E96FF", "#0089FF", "#0061B5"])
    .projection(d3.geo.mercator()
                .scale(26778)
                .translate([8227, 3207]))
    .overlayGeoJson(zaMap["features"], "name", function (d) {
        return d.properties.name;
    });

    dc.renderAll();
    $("#progress").css({"display": "none"});
})

更新2:我从小提琴切换到codepen所以我可以将geoJson文件上传为资产。 geoJson需要一段时间来加载,但是使用现有stackoverflow问题的代码,我已经得到了地图绘制和投影以自动纠正自己。 d3.js函数还没有包装dc.js以配合crossfilter.js,但我正在研究它。但这是进步:)

2 个答案:

答案 0 :(得分:1)

http://jsfiddle.net/Jimmypoo/f67xo5ry/1/中,您尝试使用JSON.parse来解析已经是JS对象的zaMapString。你不需要解析它,它不是一个字符串。

其次,d3.json用于传入远程URL,d3为您抓取。您正在尝试传入已存在的JS对象。因此,您可以删除该功能,只需在里面使用.overlayGeoJson(zaMap["features"], "name", function (d) {

你也忘了包含jQuery,但你在$("#progress").css({"display": "none"});中使用它。您还需要将整个JS部分包装在$(document).ready中。

此外,您将以缩小和未缩小的形式多次包含脚本。您只需要每个库的一个实例。

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>

<script src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.js"></script>

<script src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.min.js"></script>

您还尝试将dc的CSS包含为JavaScript。

<script src="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc.css"></script>

应该在JsFiddle的左侧资源面板中添加它。

我也不认为将#map直接分配到您文档的body会让您的工作变得更轻松......我们建议您添加内容<div id="map" style="width:100%;height:300px"></div>

这些建议并不能解决您的所有问题,但可以帮助您解决所有问题。您仍然存在预测问题。这是从http://jsfiddle.net/uggtjem6/

移动的分叉小提琴

答案 1 :(得分:0)

我已经让geoJson与d3.js,dc.js和crossfiler一起工作。

 var width  = 300;
  var height = 400;
var zaMapData = [];

//geoChoroplethChart
var zaChart = dc.geoChoroplethChart("#map");
  d3.json("https://s3-us-west-2.amazonaws.com/s.cdpn.io/384835/layer1.json", function(json) {

  var zaMap = JSON.stringify(json);
    console.log(zaMap);

      for (var i = 0; i < json.features.length; i++) { 


            console.log("ndx2 province data " + json["features"][i]["properties"]["PROVINCE"]);
            zaMapData.push({

                province: json["features"][i]["properties"]["PROVINCE"],
                donation: i*1000
            })
        };

//crossfilter instance
var ndx2 = crossfilter(zaMapData);

//dimensions and group for dc/d3
var provinceDim = ndx2.dimension(function(d) {console.log("province d " + d["province"]); return d["province"];});
var donationsByProvince = provinceDim.group().reduceSum(function(d) {
        return d["donation"];
        });
var max_province = donationsByProvince.top(1)[0].value;
      // create a first guess for the projection
      var center = d3.geo.centroid(json)
      var scale  = 150;
      var offset = [width/2, height/2];
      var projection = d3.geo.mercator().scale(scale).center(center)
          .translate(offset);

      // create the path
      var path = d3.geo.path().projection(projection);

      // using the path determine the bounds of the current map and use 
      // these to determine better values for the scale and translation
      var bounds  = path.bounds(json);
      var hscale  = scale*width  / (bounds[1][0] - bounds[0][0]);
      var vscale  = scale*height / (bounds[1][1] - bounds[0][1]);
      var scale   = (hscale < vscale) ? hscale : vscale;
      var offset  = [width - (bounds[0][0] + bounds[1][0])/2,
                        height - (bounds[0][1] + bounds[1][1])/2];

      // new projection
      projection = d3.geo.mercator().center(center)
        .scale(scale).translate(offset);
      path = path.projection(projection);


   //create dc.js chart   
      zaChart.dimension(provinceDim)
    .group(donationsByProvince)
    .width(width)
    .height(height)
    .colors(["#E2F2FF", "#C4E4FF", "#9ED2FF", "#81C5FF", "#6BBAFF", "#51AEFF", "#36A2FF", "#1E96FF", "#0089FF", "#0061B5"])
      .colorDomain([0, max_province])
    .projection(d3.geo.mercator()
              .center(center)
        .scale(scale)
              .translate(offset))
    .overlayGeoJson(json["features"], "PROVINCE", function (d) {
        return d.properties.PROVINCE;
    })
      .title(function (p) {
        return "Province: " + p["key"]
        + "\n"
        + "Total Donations: R " + Math.round(p["value"])
      });

    dc.renderAll();
    });

我的codepen在这里。