【问题标题】:Get bounding box of individual countries from topojson从 topojson 获取各个国家的边界​​框
【发布时间】:2017-11-04 20:50:20
【问题描述】:

我想从 topojson 中获取每个国家/地区的边界框,但是当我将它们添加为 svg 矩形时,它们被捆绑在一起朝向 0,0。

我重新阅读了 API 并使用了绑定坐标的顺序,但这并没有改变任何东西!另外,我尝试在国家/地区路径上使用 SVG 方法 getBBox(),但产生了相同的结果。

有什么想法吗?

var width = 700,
  height = 400,
  bboxes = [];

d3.queue()
  .defer(d3.json, "data/world.topojson")
  .await(ready);

//Map projection
var proj = d3.geoMercator()
  .scale(100)
  .center([-0.0018057527730242487, 11.258678472759552]) //projection center
  .translate([width / 2, height / 2]) //translate to center the map in view

//Generate paths based on projection
var myPath = d3.geoPath().projection(proj);

var svg = d3.select("svg"),
  width = +svg.attr("width"),
  height = +svg.attr("height");

//Group for the map features
var map = svg.append("g")
  .attr("class", "map");


function ready(error, geodata) {
  if (error) return console.log(error); //unknown error, check the console

  //Create a path for each map feature in the data
  map.selectAll("path")
    .data(topojson.feature(geodata, geodata.objects.subunits).features) //generate features from TopoJSON
    .enter()
    .append("path")
    .attr("class", "country")
    .attr("id", function(d) {
      return d.id;
    })
    .attr("d", myPath);

    bboxes = boundingExtent(topojson.feature(geodata, geodata.objects.subunits).features);


    svg.selectAll("rect")
    .data(bboxes)
    .enter()
    .append("rect")
    .attr("id", function(d){
      return d.id;
    })
    .attr("class", "bb")
    .attr("x1", function(d) {
      return d.x;
    })
    .attr("y1", function(d) {
      return d.y;
    })
    .attr("width", function(d) {
      return d.width;
    })
    .attr("height", function(d) {
      return d.height;
    })
}

function boundingExtent(features) {
var bounds= [];
  for (var x in features) {
    var boundObj = {};
    thisBounds = myPath.bounds(features[x]);
    boundObj.id = features[x].id;
    boundObj.x = thisBounds[0][0];
    boundObj.y = thisBounds[0][1];
    boundObj.width = thisBounds[1][0] - thisBounds[0][0];
    boundObj.height = thisBounds[1][1] - thisBounds[0][1];
    boundObj.path = thisBounds;
    bounds.push(boundObj)
  }
  return bounds;
}

function boundExtentBySvg(){
  var countries = svg.selectAll(".country")
  countries.each(function(d){
      var box = d3.select(this).node().getBBox();
      bboxes.push({id: d.id, x: box.x, y : box.y, width: box.width, height : box.height})
  })
}

【问题讨论】:

    标签: d3.js geojson geo topojson


    【解决方案1】:

    在这些行中:

    .attr("x1", function(d) {
      return d.x;
    })
    .attr("y1", function(d) {
      return d.y;
    })
    

    rect 没有x1y1 的属性,我想你的意思只是xy

    这是你正在运行的代码(注意,我关闭了导致轻微代码更改的 topojson 文件):

    <!DOCTYPE html>
    <html>
    
      <head>
        <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
        <script data-require="topojson.min.js@3.0.0" data-semver="3.0.0" src="https://unpkg.com/topojson@3.0.0"></script>
      </head>
    
      <body>
        <svg width="700" height="400"></svg>
        <script>
        var width = 700,
          height = 400,
          bboxes = [];
    
        d3.queue()
          .defer(d3.json, "https://unpkg.com/world-atlas@1/world/110m.json")
          .await(ready);
    
        //Map projection
        var proj = d3.geoMercator()
          .scale(100)
          .center([-0.0018057527730242487, 11.258678472759552]) //projection center
          .translate([width / 2, height / 2]) //translate to center the map in view
    
        //Generate paths based on projection
        var myPath = d3.geoPath().projection(proj);
    
        var svg = d3.select("svg"),
          width = +svg.attr("width"),
          height = +svg.attr("height");
    
        //Group for the map features
        var map = svg.append("g")
          .attr("class", "map");
    
    
        function ready(error, geodata) {
          
          if (error) return console.log(error); //unknown error, check the console
    
          //Create a path for each map feature in the data
          map.selectAll("path")
            .data(topojson.feature(geodata, geodata.objects.countries).features) //generate features from TopoJSON
            .enter()
            .append("path")
            .attr("class", "country")
            .attr("id", function(d) {
              return d.id;
            })
            .attr("d", myPath);
    
          bboxes = boundingExtent(topojson.feature(geodata, geodata.objects.countries).features);
    
    
          svg.selectAll("rect")
            .data(bboxes)
            .enter()
            .append("rect")
            .attr("id", function(d) {
              return d.id;
            })
            .attr("class", "bb")
            .attr("x", function(d) {
              return d.x;
            })
            .attr("y", function(d) {
              return d.y;
            })
            .attr("width", function(d) {
              return d.width;
            })
            .attr("height", function(d) {
              return d.height;
            })
            .style("fill", "none")
            .style("stroke", "steelblue");
        }
    
        function boundingExtent(features) {
          var bounds = [];
          for (var x in features) {
            var boundObj = {};
            thisBounds = myPath.bounds(features[x]);
            boundObj.id = features[x].id;
            boundObj.x = thisBounds[0][0];
            boundObj.y = thisBounds[0][1];
            boundObj.width = thisBounds[1][0] - thisBounds[0][0];
            boundObj.height = thisBounds[1][1] - thisBounds[0][1];
            boundObj.path = thisBounds;
            bounds.push(boundObj)
          }
          console.log(bounds)
          
          return bounds;
        }
    
        function boundExtentBySvg() {
          var countries = svg.selectAll(".country")
          countries.each(function(d) {
            var box = d3.select(this).node().getBBox();
            bboxes.push({
              id: d.id,
              x: box.x,
              y: box.y,
              width: box.width,
              height: box.height
            })
          })
        }
      </script>
      </body>
    
    </html>

    【讨论】:

    • 就是它,马克,疲惫的眼睛无法发现它。提醒自己,不要在星期五晚上晚些时候开始新代码!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 2023-01-30
    • 2014-05-15
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多