如何在 d3 js 中进行地图重投影的平滑过渡 [英] How to do smooth transition for map reprojection in d3 js

查看:22
本文介绍了如何在 d3 js 中进行地图重投影的平滑过渡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我正在构建的迷你应用程序中在 alber/orthographic 之间进行平滑过渡,就像这个例子:

I'd like to do a smooth transition between alber/orthographic in a mini app I am building, much like this example:

http://mbostock.github.io/d3/talk/20111018/#27

似乎这种平滑过渡在 v3 中被打破了,地图路径的过渡相当不稳定:

It seems like this smooth transition is broken in v3 however, with a rather choppy transition of the map paths:

https://www.evernote.com/shard/s236/sh/46b002bd-9c5b-4e9b-87ef-270c303eb677/2eaeebb28597a35cc584b3753757d385c587000-b534-31a3e3034762/Worst_Tornado_Outbreaks_of_All_Time-20130611-074050.jpg.jpg?resizeSmall&width=832

代码非常简单,我将地图初始化为 albers,然后运行 ​​ortho() 来更新它.

Code is pretty straight forward, I initialize the map as albers, then run ortho() to update it.

function ortho() {
  var self = this, 
    h = 1000,
    w = document.width;

  this.projection = d3.geo.orthographic()
    .scale(500)
    .translate([ (w - 300) / 2, h / 2])
    .clipAngle(90)
    .rotate([90, 0, 0])
    .precision(.1);

  this.path = d3.geo.path()
    .projection(this.projection);

  //update path WITH transition
  d3.selectAll('path')
    .transition()
    .duration(900)
    .attr('d', app.path);

}

地图从albers变成orthographic,但是过渡不平滑.任何想法都会很棒.

The map changes from albers to orthographic, but the transition is not smooth. Any thoughts would be great.

推荐答案

如果您使用 D3 的简单字符串插值器对路径进行插值 (d3.interpolateString),那么起始路径中的坐标数和结束路径中的坐标数必须完全匹配,包括顺序相同.但由于剪裁、剪切重采样.形状插值是可能的(使用多个 策略),但它是在一般情况下很难解决的问题.请参阅此说明(Path Transitions) 解释了为什么朴素插值是不够的.

If you interpolate the path using D3’s naïve string interpolator (d3.interpolateString), then the number of coordinates in the starting path and the number of the coordinates in the ending path must match exactly, including in the same order. But this is almost never the case due to clipping, cutting and resampling. Shape interpolation is possible (using multiple strategies), but it’s a hard problem to solve in the general case. See this explanation (part of the Path Transitions) for why naïve interpolation is insufficient.

您想对投影进行插值,而不是对路径进行插值. 对投影进行插值不需要坐标之间的精确对应关系,因此可以避免插值伪影.请参阅以下示例进行演示:

Instead of interpolating the path, you want to interpolate the projection. Interpolating the projection does not require an exact correspondence between coordinates and therefore avoids interpolation artifacts. See these examples for a demonstration:

如第一个示例所示,您可以使用以下实现:

As shown in the first example, here is an implementation you can use:

function interpolatedProjection(a, b) {
  var projection = d3.geo.projection(raw).scale(1),
      center = projection.center,
      translate = projection.translate,
      α;

  function raw(λ, φ) {
    var pa = a([λ *= 180 / Math.PI, φ *= 180 / Math.PI]), pb = b([λ, φ]);
    return [(1 - α) * pa[0] + α * pb[0], (α - 1) * pa[1] - α * pb[1]];
  }

  projection.alpha = function(_) {
    if (!arguments.length) return α;
    α = +_;
    var ca = a.center(), cb = b.center(),
        ta = a.translate(), tb = b.translate();
    center([(1 - α) * ca[0] + α * cb[0], (1 - α) * ca[1] + α * cb[1]]);
    translate([(1 - α) * ta[0] + α * tb[0], (1 - α) * ta[1] + α * tb[1]]);
    return projection;
  };

  delete projection.scale;
  delete projection.translate;
  delete projection.center;
  return projection.alpha(0);
}

使用两个投影ab创建内插投影,然后将内插alpha设置为0之间的值(对于a)和 1(对于 b).

Create the interpolated projection using two projections a and b, and then set the interpolated alpha to a value between 0 (for a) and 1 (for b).

这篇关于如何在 d3 js 中进行地图重投影的平滑过渡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆