关注 D3.js 地图中的 geojson
Focusing on geojson in D3.js map
我正在尝试查看 topojson 文件(城市中的建筑物)中的对象,但出现以下错误:
Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…".
这是我的代码:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.land {
fill: #e5e5e5;
stroke: #000;
stroke-width: 0.2;
stroke-opacity: 0.8;
}
.states {
fill: none;
stroke: #fff;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script>
<script>
var width = 800;
var height = 600;
var projection = d3.geo.mercator()
.center([30, 30])
.scale(500)
.translate([width / 2, height / 2]);
var path = d3.geo.path().projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
queue()
.defer(d3.json, "cairomonuments.json")
.await(ready);
function ready(error, cairo) {
if (error) throw error;
// Refine projection
var b, s, t;
projection.scale(1).translate([0, 0]);
var b = path.bounds(cairo);
var s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
projection.scale(s).translate(t);
svg.selectAll("path")
.data(topojson.feature(cairo, cairo.objects.monuments).features)
.enter()
.append('path')
.attr('class', 'land')
.attr('d', path);
}
</script>
</body>
我只想将地图置于我的 geojson 文件的中心,然后将其横向翻转。我错过了什么?
问题
据我所知,主要问题是这一行:
var b = path.bounds(cairo);
path.bounds
不会通过要素集合(例如您的图层)产生预期的结果。 Instead it:
Computes the projected bounding box (in pixels) for the specified
feature. The bounding box is represented by a two-dimensional array:
[[left, top], [right, bottom]] , different from GIS geo.bounds'
convention.
此外,您传递的不是 geojson,而是 topojson。如果您想使用特定功能的边界,您的代码看起来更像:
var b = path.bounds(topojson.feature(cairo, cairo.objects.monuments).features[0]);
即使你以正确的格式传递给它一个单一的特征,它仍然不会正确投影,因为你的比例在你之前定义投影时被定义为 500 - 这会在动态重新计算时扭曲计算规模。
可能的解决方案(保持 d3.js v3)
Topojson一般有一个bbox
属性。您可以使用它来获取居中坐标:
var x = (cairo.bbox[0] + cairo.bbox[2]) / 2; // get middle x coordinate
var y = (cairo.bbox[1] + cairo.bbox[3]) / 2; // get middle y coordinate
请注意,geojson 或 topojson 边界框的顺序是:左、下、右、上。
所以我们现在可以轻松地将地图居中放置在图层中心:
projection.center([x,y])
或 projection.rotate([-x,0]).center([0,y])
或 projection.rotate([-x,-y])
.
现在剩下的就是计算比例(设置为一开始)。
如果path.bounds
returns左上角和右下角坐标的二坐标数组([min x, min y],[max x, max y],在SVG坐标中space), 那么我们可以使用 topojson.bbox:
生成一个等价的数组
var b = [ projection([cairo.bbox[0],cairo.bbox[3]]),projection([cairo.bbox[2],cairo.bbox[1]]) ];
这里有点棘手,因为 SVG 坐标 space 的 y 坐标从顶部的零开始(与地理特征相反),边界中的坐标顺序是: 左上右下(同样不同于地理特征)。
这给我们留下了您已经进行的计算:
var s = 0.95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
这总共给了我们:
初始规模申报:
var projection = d3.geo.mercator()
.scale(1)
.translate([width / 2, height / 2]);
基于数据层的比例和中心细化:
var x = (cairo.bbox[0] + cairo.bbox[2]) / 2;
var y = (cairo.bbox[1] + cairo.bbox[3]) / 2;
projection.rotate([-x,-y]);
var b = [ projection([cairo.bbox[0],cairo.bbox[3]]),projection([cairo.bbox[2],cairo.bbox[1]]) ];
var s = 0.95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
projection.scale(s);
这里是 a bl.ock 演示的全部内容。
翻转地图
投影旋转中有一个很少使用的参数可以实现这一点。在我上面的 bl.ock 和上面的代码块中,我使用旋转来使地图投影居中。通过添加第三个参数,我可以相对于视口旋转地图:
projection.rotate([-x,-y,90]);
我正在尝试查看 topojson 文件(城市中的建筑物)中的对象,但出现以下错误:
Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…".
这是我的代码:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.land {
fill: #e5e5e5;
stroke: #000;
stroke-width: 0.2;
stroke-opacity: 0.8;
}
.states {
fill: none;
stroke: #fff;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script>
<script>
var width = 800;
var height = 600;
var projection = d3.geo.mercator()
.center([30, 30])
.scale(500)
.translate([width / 2, height / 2]);
var path = d3.geo.path().projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
queue()
.defer(d3.json, "cairomonuments.json")
.await(ready);
function ready(error, cairo) {
if (error) throw error;
// Refine projection
var b, s, t;
projection.scale(1).translate([0, 0]);
var b = path.bounds(cairo);
var s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
var t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
projection.scale(s).translate(t);
svg.selectAll("path")
.data(topojson.feature(cairo, cairo.objects.monuments).features)
.enter()
.append('path')
.attr('class', 'land')
.attr('d', path);
}
</script>
</body>
我只想将地图置于我的 geojson 文件的中心,然后将其横向翻转。我错过了什么?
问题
据我所知,主要问题是这一行:
var b = path.bounds(cairo);
path.bounds
不会通过要素集合(例如您的图层)产生预期的结果。 Instead it:
Computes the projected bounding box (in pixels) for the specified feature. The bounding box is represented by a two-dimensional array: [[left, top], [right, bottom]] , different from GIS geo.bounds' convention.
此外,您传递的不是 geojson,而是 topojson。如果您想使用特定功能的边界,您的代码看起来更像:
var b = path.bounds(topojson.feature(cairo, cairo.objects.monuments).features[0]);
即使你以正确的格式传递给它一个单一的特征,它仍然不会正确投影,因为你的比例在你之前定义投影时被定义为 500 - 这会在动态重新计算时扭曲计算规模。
可能的解决方案(保持 d3.js v3)
Topojson一般有一个bbox
属性。您可以使用它来获取居中坐标:
var x = (cairo.bbox[0] + cairo.bbox[2]) / 2; // get middle x coordinate
var y = (cairo.bbox[1] + cairo.bbox[3]) / 2; // get middle y coordinate
请注意,geojson 或 topojson 边界框的顺序是:左、下、右、上。
所以我们现在可以轻松地将地图居中放置在图层中心:
projection.center([x,y])
或 projection.rotate([-x,0]).center([0,y])
或 projection.rotate([-x,-y])
.
现在剩下的就是计算比例(设置为一开始)。
如果path.bounds
returns左上角和右下角坐标的二坐标数组([min x, min y],[max x, max y],在SVG坐标中space), 那么我们可以使用 topojson.bbox:
var b = [ projection([cairo.bbox[0],cairo.bbox[3]]),projection([cairo.bbox[2],cairo.bbox[1]]) ];
这里有点棘手,因为 SVG 坐标 space 的 y 坐标从顶部的零开始(与地理特征相反),边界中的坐标顺序是: 左上右下(同样不同于地理特征)。
这给我们留下了您已经进行的计算:
var s = 0.95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
这总共给了我们:
初始规模申报:
var projection = d3.geo.mercator()
.scale(1)
.translate([width / 2, height / 2]);
基于数据层的比例和中心细化:
var x = (cairo.bbox[0] + cairo.bbox[2]) / 2;
var y = (cairo.bbox[1] + cairo.bbox[3]) / 2;
projection.rotate([-x,-y]);
var b = [ projection([cairo.bbox[0],cairo.bbox[3]]),projection([cairo.bbox[2],cairo.bbox[1]]) ];
var s = 0.95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height);
projection.scale(s);
这里是 a bl.ock 演示的全部内容。
翻转地图
投影旋转中有一个很少使用的参数可以实现这一点。在我上面的 bl.ock 和上面的代码块中,我使用旋转来使地图投影居中。通过添加第三个参数,我可以相对于视口旋转地图:
projection.rotate([-x,-y,90]);