如何在 d3.js 中同步地图和点图层的比例和位置?
Posted
技术标签:
【中文标题】如何在 d3.js 中同步地图和点图层的比例和位置?【英文标题】:How do I synchronize scale and position of map and point layers in d3.js? 【发布时间】:2018-09-21 18:53:40 【问题描述】:我在 d3 中看到了许多示例地图,其中添加到地图的点会按预期自动对齐,但在我改编自 http://bl.ocks.org/bycoffe/3230965 的代码中,我添加的点与下面的地图不对齐。
此处的示例:https://naltmann.github.io/d3-geo-collision/ (积分应该与美国一些主要城市相匹配)
我很确定差异是由于围绕比例/范围的代码,但我不知道如何在地图和点之间统一它们。
【问题讨论】:
力布局通常意味着您让预定义的力至少在一定程度上定位元素,这反过来意味着牺牲了地理准确性。如果您希望每个点与其坐标对齐,为什么不使用它们的坐标来放置它们呢?我觉得我在这个问题上遗漏了一些东西。 @AndrewReid 感谢您的回复。代码使用坐标定位点,然后使用碰撞逻辑将它们分散开,这样它们就不会接触。这会将它们从真实坐标移开,但我遇到的问题比这更基本。我似乎有 2 层彼此没有坐标关系(比例、位置等)。我调整了一些范围/比例值以使它们看起来很接近,但它们并没有像应有的那样真正联系在一起。我认为我正在 mssing d3 组装 svg 的方式有一些基本的东西。 好吧,我确实仔细看了看,这种方法让我觉得很奇怪,我想我从来没有见过 x 和 y 的比例来放置地理坐标。可能有一种方法可以在没有尺度的情况下解决这个问题。今天我将尝试对此进行更多检查 - 尽管我全神贯注于一些泛滥的情况。 再次感谢。毫无疑问,当我试图从原始代码中进行调整时,我发现了一些非常糟糕的东西。不过建议不错,我看看能否去掉 x 和 y 比例部分。 我希望我的回答是有用的,这是一个有趣的问题 - 我喜欢看到不同的解决方案来放置像你这样的标记(特别是与地理标签放置有关 - 这经常证明一个问题) . 【参考方案1】:在地理上将地理特征与您的示例对齐将具有挑战性 - 首先您要投影点,然后缩放 x,y:
node.cx = xScale(projection(node.coordinates)[0]);
node.cy = yScale(projection(node.coordinates)[1]);
刻度的范围很有趣,因为两个范围的两个限制都是负数,这可能是由于点上力的累积性质而试图纠正点的定位:
.on('tick', function(e)
k = 10 * e.alpha;
for (i=0; i < nodes.length; i++)
nodes[i].x += k * nodes[i].cx
nodes[i].y += k * nodes[i].cy
这很有挑战性,就好像我们移除了尺度一样,这些点向右和向下移动得越来越远。这种累积性质意味着,随着每一个刻度,这些点会越来越远离可识别的地理坐标。这在处理一组经历相同变换的地理数据时很好,但在处理没有经历相同变换的背景时,就有点困难了。
我会注意,如果您想要地图宽度为 1800,高度为 900,则应将墨卡托投影的平移设置为 [1800/2,900/2]
,并将比例设置为 1800/Math.PI/2
地理坐标和力坐标之间的脱节似乎很难纠正。这种特定布局和尺寸的任何解决方案都可能在不同的布局和尺寸上失败。
相反,我建议尝试仅使用投影来放置坐标,而不是累积地向每个点添加力变化。这是对您问题的简短回答。
对于更长的答案,我的第一个想法是摆脱碰撞功能并使用链接到每个城市的浮点的锚点,仅绘制浮点(使用链接距离使它们保持接近)。这可能是一种更清洁的解决方案,但不幸的是,它与您尝试的完全不同。
但是,我的第二个想法更倾向于保留您的示例,但删除比例(和累积力)并将力减少到零,以便碰撞功能可以不受干扰地工作。基于这些想法,这里有一个可能的解决方案demonstration。
【讨论】:
以上是关于如何在 d3.js 中同步地图和点图层的比例和位置?的主要内容,如果未能解决你的问题,请参考以下文章