【问题标题】:How does d3's path.bounds work?d3 的 path.bounds 是如何工作的?
【发布时间】:2016-10-23 09:17:13
【问题描述】:

我有一个 TopoJson 格式的文件 world.topo.json,我从 https://datamaps.github.io/ 获取并在 d3 地理图表中使用它(使用 merchant 投影)。

效果很好,但是当我调用path.bounds(<TopoJson File Content>.objects.world.feature) 并获得这些值时,我觉得很奇怪:

[
    [-25.272818452358365, -114.9648719971861],
    [917.2049776245796, 507.5180814546301]
]

那么,为什么底部/左角指向 -25 和 -114?它们不应该是0,0 或-917, -507 吗?

更新:我有一个缩放行为对象绑定到我的 d3 图表,完全符合我的预期。因此,我为每次缩放/拖动都写了一个console.log,如下所示:

const topojson = <response of an ajax request>;
const bounds = path.bounds(topojson.objects.world.feature);
console.log(translate, JSON.stringify(path.bounds(feature))); // XXX

所以,每次缩放/拖动甚至被调用,这就是我得到的输出类型:

[25, 120] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"

第一个数组是当前的translate,第二个是边界。

但是,当我拖动/平移或缩放时,输出如下:

[0.021599999999999998, 0.10368] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[24.88185889212827, 119.4329226822157] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[25, 120] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[25, 120] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-15, 119] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-27, 117] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-27.32184332502962, 117.03468139278337] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-125.83796642848066, 127.65064293410353] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-165.15379127139124, 131.88726199045166] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-173.98081187505056, 132.83844955550114] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-173.98081187505056, 132.83844955550114] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-173.4557969093005, 132.7818746669505] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-89.06290511198648, 123.68781305086063] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"
[-89.06290511198648, 123.68781305086063] "[[-25.272818452358365,-114.9648719971861],[917.2049776245796,507.5180814546301]]"

如您所见,尽管第一个参数会根据缩放和平移事件不断变化,但边界保持不变。

【问题讨论】:

    标签: d3.js topojson datamaps


    【解决方案1】:

    关于path.bounds(object)的documentation已经覆盖了:

    返回指定 GeoJSON 对象的投影平面边界框(通常以像素为单位)。边界框由一个二维数组表示:[[x₀, y₀], [x₁, y₁]],其中x₀是最小x坐标,y₀是最小y坐标,x₁是最大x坐标, y₁ 是最大的 y 坐标。

    因此,-25 和 -114 是最小的 x 和 y 值,并且指的是 左上角 角(在 SVG 坐标系中),而不是左下角。

    请记住,path.bounds 与 geoBounds 不同,后者:

    返回指定 GeoJSON 特征的球形边界框。边界框用二维数组表示:[[left, bottom], [right, top]],其中left为最小经度,bottom为最小纬度,right为最大经度,top为最大纬度.

    它是如何工作的?

    path.bounds(object) 将使用您的投影在对象周围绘制一个“矩形”,并将返回一个包含该矩形四个角的数组,如上所述。让我们看看它在这些演示中是如何工作的(这段代码不是我的):

    在第一个演示中,日本地图的比例尺为 1000。检查控制台以查看 path.bounds。

    var topoJsonUrl = "https://dl.dropboxusercontent.com/u/1662536/topojson/japan.topo.json";
    
    var width = 500,
        height = 500,
        scale = 1;
    
    d3.select("body").append("svg")
    	.attr("width", width)
    	.attr("height", height)
        .append("g").attr("id", "all-g");
    
    var projection = d3.geo.mercator()
    		.center([138, 38])
    		.scale(1000)
    		.translate([width / 2, height / 2]);
        
    d3.json(topoJsonUrl, onLoadMap);
    
    function onLoadMap (error, jpn) {
        var path = d3.geo.path()
            		.projection(projection);
    	var features = topojson.object(jpn, jpn.objects.japan);
      
      var mapJapan = features;
      
     console.log(JSON.stringify(path.bounds(mapJapan)))
      
    
    	d3.select("#all-g")
            .append("g").attr("id", "path-g").selectAll("path")
                .data(features.geometries)
                .enter()
                .append("path")
                .attr("fill", "#f0f0f0")
                .attr("id", function(d,i){ return "path" + i})
                .attr("stroke", "#999")
                .attr("stroke-width", 0.5/scale)
                .attr("d", path);
    
    }
    path {
      stroke: black;
      }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <script src="https://d3js.org/topojson.v0.min.js"></script>

    它记录:

    [[-12.878670523380151,73.71036362631844],[529.0014631418044,535.5463567314675]]
    

    哪些是 [[x0, y0],[x1, y1]] 值。

    现在是相同的代码,但比例为 500:

    var topoJsonUrl = "https://dl.dropboxusercontent.com/u/1662536/topojson/japan.topo.json";
    
    var width = 500,
        height = 500,
        scale = 1;
    
    d3.select("body").append("svg")
    	.attr("width", width)
    	.attr("height", height)
        .append("g").attr("id", "all-g");
    
    var projection = d3.geo.mercator()
    		.center([138, 38])
    		.scale(500)
    		.translate([width / 2, height / 2]);
        
    d3.json(topoJsonUrl, onLoadMap);
    
    function onLoadMap (error, jpn) {
        var path = d3.geo.path()
            		.projection(projection);
    	var features = topojson.object(jpn, jpn.objects.japan);
      
      var mapJapan = features;
      
     console.log(JSON.stringify(path.bounds(mapJapan)))
      
    
    	d3.select("#all-g")
            .append("g").attr("id", "path-g").selectAll("path")
                .data(features.geometries)
                .enter()
                .append("path")
                .attr("fill", "#f0f0f0")
                .attr("id", function(d,i){ return "path" + i})
                .attr("stroke", "#999")
                .attr("stroke-width", 0.5/scale)
                .attr("d", path);
    
    }
    path {
      stroke: black;
      }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <script src="https://d3js.org/topojson.v0.min.js"></script>

    它记录不同的值:

    [[118.56066473830992,161.85518181315928],[389.5007315709022,392.77317836573377]]
    

    【讨论】:

    • 好吧,好吧,我得到了底部/左侧与顶部/左侧,但我的问题是为什么它是 -25/-114 而其他坐标是 917, 507 ?我的意思是,它如何找到这样的数字?对我来说,逻辑值应该是 0,0 或其他坐标中相同值的负数。你明白我的意思吗? -25 和 917 之间以及 -113 和 507 之间没有逻辑关系。这些值是从哪里产生的?我知道它们不是绝对值,它们会根据 GeoJSON/TopoJSON 内容而有所不同,我知道。我的意思是:为什么 -25 而另一个是 917?
    • 感谢您的努力,但我认为您还没有收到我的问题。看到 -12 和 529 之间没有相关性吗?我的意思是,不应该是 0 和 541 吗?或者如果中间有 0,0,可能是 -270.5 和 270.5?我的意思是为什么是-12?再说一遍:从逻辑上讲,当它输出宽度为 541 的矩形的边界时,左边应该是 0,右边应该是 541。它返回该数字一定有某种原因。我知道比例会改变输出,但不管比例如何,仍然很难理解为什么 118 和 389,你能看到吗?
    • 你说的毫无意义。为什么要从0开始?为什么 0 应该在中间?它返回矩形在 SVG 坐标系中的位置,相对于它所在的 SVG。在上面的演示中更改翻译,您将看到四个值发生变化。我不能比我已经解释的更多了。请查看 SVG 坐标系统和 D3 投影功能。这也是一个很好的阅读:jasondavies.com/maps/bounds
    • “相对于它所在的 SVG”
    • @MarinhoBrandão 关于您的编辑:path.bounds(object) 取决于投影。您正在翻译元素在投影工作之后。
    猜你喜欢
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    相关资源
    最近更新 更多