无法使标签与D3平铺投影一起使用

时间:2018-06-16 20:01:32

标签: javascript d3.js

我正在尝试将一些简单的国家标签添加到D3矢量地图中,该地图位于D3平铺栅格地图的顶部。正在按预期创建标签,但我无法在地图上正确投影它们。 D3-tile中的投影有点混乱(我的意思是它不像'普通'矢量地图那样工作,我不明白它。)

我有created a jsfiddle我在其中创建地图,然后尝试投影它们,以便它们随着用户交互而移动。

无法实现此目的的代码位于:

  d3.selectAll(".country_labels")   
    .attr("transform", function(d) {return "translate(" + path.centroid(d) + ")"})  

更新

我怀疑我在这个问题上的问题类似于raised earlier today on here。我还注意到类似的问题was raised here too

我已经取得了一些进展并将这个新fiddle放在一起。标签现在都在地图上,但漂浮在几内亚湾附近,靠近地理坐标[0,0]。对我来说,这意味着他们可能已经正确投影但是缩放功能没有按预期运行。这里的问题是这个脚本中有三种不同类型的坐标:

  1. Geocoordinates - 这些是起点并且始终是固定的
  2. 'd3-tile'坐标。适合单个像素的那些,因此总是非常接近零
  3. 像素坐标 - 这些对应于屏幕上的实际坐标

1 个答案:

答案 0 :(得分:1)

这与你的其他问题相似,只是它在前向投影&缩放而不是反转。 (我在更新之前开始写这个,但必须运行,我将继续使用您的原始代码)。

与路径一样,您可以按预期附加标签:

country_labels.selectAll("text")
  .data(collection.features)
  .enter().append("text")
  .attr("x", function(d){return path.centroid(d)[0];})
  .attr("y", function(d){return path.centroid(d)[1];})
  .attr("dx", -40)
  .text(function(d){ return d.properties.name })
  .style("fill", "#aeaeaf") 
  .style("font-size", "15px")

这里有一个问题,因为大多数d3-tiles示例的投影,包括你的,使用1 / tau的d3投影比例,世界投影在1个像素的空间内,所以dx值等于40个世界,这在应用缩放时不起作用,所以让我们放弃那个部分

现在,您或多或少地追加功能,就像路径一样,但问题在于缩放处理:

d3.selectAll(".country_labels") 
  .attr("transform", function(d) {return "translate(" + path.centroid(d) + ")"})    

路径也有类似的处理方式:

vector
    .attr("transform", "translate(" + [transform.x, transform.y] + ")scale(" + transform.k + ")")
    .style("stroke-width", 1 / transform.k); 

但这里有一些不同之处:

  1. 与文本相比,您正在对路径应用不同的变换(缩放和平移):对于文本,没有对当前缩放变换的引用,而是仅使用锚定的投影在0,0处,所有特征都位于一个像素的区域内(并且锚定在0,0将在y = 0处具有其基线,文本将基本上不在视图中)。如果你检查svg,你会看到文本,只是在错误的位置。

  2. 当一个放大时,路径的笔划宽度减小(因为我们正在缩放svg,笔划宽度本身会增加),同样适用于文本,因此即使文本正确定位,它也会非常大(超过大多数屏幕拿着浏览器)。

  3. 我们可以解决这个问题的一种方法是在文本的x / y坐标上应用缩放变换,而不是元素本身(这也会缩放文本大小,这样我们就不需要调整大小所有文字):

    country_labels.selectAll("文本&#34)     .attr(" x",function(d){return transform.apply(path.centroid(d))[0];})     .attr(" y",function(d){return transform.apply(path.centroid(d))1;})

    inversion from svg pixel to lat/long一样,我们会进行相同的动作,但顺序相反:应用投影,然后应用缩放。

    这里是updated fiddle

    但是,我有一个坏消息 - 标签的位置正好在你告诉他们现在定位的地方。但是它们并不是你想要它们的地方(这是怎么回事,关于编程的最好的事情是代码完全按照你说的去做,最糟糕的事情是编程是代码完全按照你的说法进行的吗?)。

    您正在使用路径质心来放置标签,这有时适用于某些功能,但它并不是一直有效。以美国为例,使用墨卡托投影的美国质心在美国并不是因为它位于阿拉斯加州和48个州之间(对不起夏威夷,你在这里没有太大的吸引力) 。加拿大的质心部分位于北冰洋,在许多数据集中(不是令人惊讶的是),法国在大西洋中部由于法国圭亚那而被标记为使用质心作为文本锚点。

    您可以使用.style("text-anchor","middle")稍微改善视觉外观,{{1}}至少将标签居中(对于较小或平等的国家非常有用),但最终质心放置并非理想。

    我刚刚完成:注释是制图的祸根。

    但是,有希望,here's我见过的更有希望的未来之一。