【问题标题】:Animating circle clip on D3 Geo AzimuthalD3 Geo Azimuthal 上的动画圆形剪辑
【发布时间】:2013-09-13 06:04:08
【问题描述】:

我正在搞乱 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());

我将尝试设置一个小提琴作为错误的示例。谢谢!

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

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

    为此,您需要在新旧来源之间设置interpolation function。然后,您将使用setTimeout 以下列方式递归调用具有中间起源的navigateGlobe

    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)决定。总数需要与您的其他过渡相同。

    【讨论】:

    • 我对此进行了修改,现在得到了一些合理的结果,因此我将其标记为已回答。不幸的是,我能找到的唯一方法是使用插值器为投影的比例和原点设置动画,同时作为剪裁圆的原点。这消除了您通过过渡获得的良好缓动效果。有没有办法把这个找回来? (我已经看到有一种叫做“基础”插值的东西,看起来它会做我想做的事情,但是我认为我不能在这里将它应用到插值上)
    • 不看代码就无法判断是否可以进行缓动。如果您就此提出一个单独的问题可能会很好。
    • 我看不到可以使用的内置缓动函数,但我自己做了,而不是线性 setNewOrigin(count+1) 递归,它执行 (count+i),其中 i 增加从 0 到 count > iters/2,然后减少回 0。感谢您的帮助!
    • D3 中有几个内置的缓动函数。那些不合适?
    【解决方案2】:

    这实际上是可行的,根据所有建议,使用 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);
    

    【讨论】:

      猜你喜欢
      • 2018-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 2023-03-26
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多