从 topojson 获取各个国家的边界框
Posted
技术标签:
【中文标题】从 topojson 获取各个国家的边界框【英文标题】:Get bounding box of individual countries from 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)
)
【问题讨论】:
【参考方案1】:在这些行中:
.attr("x1", function(d)
return d.x;
)
.attr("y1", function(d)
return d.y;
)
rect
没有x1
或y1
的属性,我想你的意思只是x
和y
。
这是你正在运行的代码(注意,我关闭了导致轻微代码更改的 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 ></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>
【讨论】:
就是它,马克,疲惫的眼睛无法发现它。提醒自己,不要在星期五晚上晚些时候开始新代码!以上是关于从 topojson 获取各个国家的边界框的主要内容,如果未能解决你的问题,请参考以下文章