0

我正在搞乱 d3.geo.azimuthal 的版本,如下所示:http: //mbostock.github.io/d3/talk/20111018/azimuthal.html

我有一个导航到特定大陆的链接列表。这些都调用了一个自定义函数 navigateGlobe,其中包含有关移动到哪里的信息。

function navigateGlobe(orig, scal) {
    projection.origin(orig);
    projection.scale(scal);
    refresh(1500);
}

刷新功能与源示例中的相同,如下所示:

function refresh(duration) {
    (duration ? feature.transition().duration(duration) : feature).attr("d", clip);
}

在运行 navigateGlobe 时,它​​可以正常工作,并且投影会平滑过渡到所需的位置和比例,但是在鼠标下一次移动地球之前,剪裁圆不会更新。我知道剪裁是由圆圈完成的,以隐藏地球一侧背对用户的国家,所以我改变了我的功能:

function navigateGlobe(orig, scal) {
    projection.origin(orig);
    projection.scale(scal);
    circle.origin(orig); // Need to animate this!
    refresh(1500);
}

剪裁圆现在会更新,但会立即更新,即在动画的第 1 步达到目标剪裁点。我想知道是否有办法以与投影相同的速率转换剪切圆,以便整个动画看起来很流畅。

作为参考,再次与源示例一样, var circle 设置为:

var circle = d3.geo.greatCircle()
    .origin(projection.origin());

我将尝试设置一个小提琴作为出了什么问题的例子。谢谢!

4

2 回答 2

1

不幸的是,这是一个 D3 的转换有点短的例子——你不能真正地只转换值。您可以设置自己的缓动函数,但您需要使用正确的值手动调用它。

为此,您将在新旧原点之间设置一个插值函数。然后,您将以以下方式navigateGlobe递归调用中间源。setTimeout

var interpolator = d3.interpolate(...);
var iters = 10;
function setNewOrigin(count) {
    setTimeout(function() {
        navigateGlobe(interpolator(count/iters));
        if(count < iters) setNewOrigin(count + 1);
    }, 10);
}
setNewOrigin(1);

这个过渡的持续时间由迭代次数(这里是 10)和递归调用的超时值(这里是 10ms,即总共 100ms)决定。总数需要与您的其他过渡相同。

于 2013-09-09T17:36:18.583 回答
0

根据所有建议,这实际上是有效的,使用 requestAnimationFrame

    var o = projection.origin();

    var si = d3.interpolate(projection.scale(), SCALE);
    var xi = d3.interpolate(o[0], -58.4459789 +10);
    var yi = d3.interpolate(o[1], -34.612869   -4); // buenos aires -4°

    function xanimate (fn, time) {
        var start = null;

        function step(timestamp) {
            var progress;
            if (start === null) start = timestamp;
            progress = timestamp - start;
            var p = progress / time;
            fn (p);
            if (progress < time) {
                requestAnimationFrame(step);
            }
        }

        requestAnimationFrame(step);
    }

    function navigateGlobe(orig, scal) {
        projection.origin(orig);
        projection.scale(scal);
        circle.origin(orig); // Need to animate this!
        refresh();
    }

    xanimate (function (t) {
        navigateGlobe ([xi(t), yi(t)], si(t));
    }, 2000);
于 2014-06-11T11:38:00.457 回答