且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 d3 js 中进行地图重投影的平滑过渡

更新时间:2023-10-27 22:54:16

如果您使用 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).