【发布时间】:2013-06-29 19:14:35
【问题描述】:
如何对地图的标签施加力排斥,以便它们自动找到正确的位置?
博斯托克的“让我们做一张地图”
Mike Bostock 的 Let's Make a Map(截图如下)。默认情况下,标签放置在点的坐标和多边形/多边形的path.centroid(d) + 简单的左对齐或右对齐,因此它们经常发生冲突。
手工标签放置
I met 的一项改进需要添加人工修复的IF,并根据需要添加任意数量的修复程序,例如:
.attr("dy", function(d){ if(d.properties.name==="Berlin") {return ".9em"} })
随着要重新调整的标签数量的增加,整体变得越来越脏:
//places's labels: point objects
svg.selectAll(".place-label")
.data(topojson.object(de, de.objects.places).geometries)
.enter().append("text")
.attr("class", "place-label")
.attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
.attr("dy", ".35em")
.text(function(d) { if (d.properties.name!=="Berlin"&&d.properties.name!=="Bremen"){return d.properties.name;} })
.attr("x", function(d) { return d.coordinates[0] > -1 ? 6 : -6; })
.style("text-anchor", function(d) { return d.coordinates[0] > -1 ? "start" : "end"; });
//districts's labels: polygons objects.
svg.selectAll(".subunit-label")
.data(topojson.object(de, de.objects.subunits).geometries)
.enter().append("text")
.attr("class", function(d) { return "subunit-label " + d.properties.name; })
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr("dy", function(d){
//handmade IF
if( d.properties.name==="Sachsen"||d.properties.name==="Thüringen"|| d.properties.name==="Sachsen-Anhalt"||d.properties.name==="Rheinland-Pfalz")
{return ".9em"}
else if(d.properties.name==="Brandenburg"||d.properties.name==="Hamburg")
{return "1.5em"}
else if(d.properties.name==="Berlin"||d.properties.name==="Bremen")
{return "-1em"}else{return ".35em"}}
)
.text(function(d) { return d.properties.name; });
需要更好的解决方案
这对于较大的地图和标签集是无法管理的。 如何为这两个类添加力排斥:.place-label 和 .subunit-label?
这个问题是一场头脑风暴,因为我没有截止日期,但我很好奇。我正在考虑将这个问题作为 Migurski/Dymo.py 的基本 D3js 实现。 Dymo.py 的 README.md 文档设置了大量的目标,从中选择核心需求和功能(20% 的工作,80% 的结果)。
- 初始放置: Bostock 以相对于地理点的左/右定位提供了一个良好的开端。
- 标签间排斥:可以采用不同的方法,Lars 和 Navarrc 分别提出了一种,
-
标签湮灭:标签湮灭函数,当一个标签的整体排斥太强烈时,因为挤压在其他标签之间,湮灭的优先级是随机的或基于
population数据值,我们可以通过 NaturalEarth 的 .shp 文件获取。 - [Luxury] 标签到点排斥:带有固定点和移动标签。但这相当奢侈。
我忽略了标签排斥是否会跨标签层和标签类别起作用。但是让国家标签和城市标签不重叠也可能是一种奢侈。
【问题讨论】:
-
我认为向地点标签添加强制排斥力可以使一些标签脱离其各自的区域。另一件需要考虑的事情是,不同类型的标签可以在某些地图中重叠,城市名称可以覆盖国家名称,但字体非常不同。我认为最终的解决方案可能会更复杂,只是增加了排斥力。
-
我在这里使用了强制布局来定位标签:larsko.org/v/igdp/index-alt.html 你的情况比较复杂,因为它涉及到两个维度,但你也许可以重用一些代码。
-
@PabloNavarro:首先,如何对我的物品施加排斥力。后来,力量可能是微妙的。它需要一个随距离迅速减小的斥力,R = 1/x。这种调整将是另一个问题。
-
我实现了上述策略的演示。它并不完美,但它可以提供帮助。 bl.ocks.org/pnavarrc/5913636
-
我知道这与强制排斥无关,但正如 Mike Bostock 在教程中指出的那样,有这个脚本 github.com/migurski/Dymo 应该可以解决问题(我无法让它工作tho,我什至在这里发布了一个问题以获得一些建议,但希望你可以!)
标签: d3.js maps force-layout topojson cartography