d3沿SVG路径的稳定水平过渡

时间:2014-09-04 00:00:28

标签: javascript svg d3.js

我使用d3 attrTween平滑地在路径上翻译圆圈,类似于this example,如下图所示:

Graph

圆圈的过渡在此处定义:

function transition() {
    circle.transition()
    .duration(2051)
    .ease("linear")
    .attrTween("transform", translateAlong(path.node()))
}

此处显示了补间属性:

function translateAlong(path) {
    var l = path.getTotalLength();
    return function (d, i, a) {
        return function (t) {
            var p = path.getPointAtLength(t * l);
            return "translate(" + p.x + "," + p.y + ")";
        };
    };
}

这要归功于SVG方法getPointAtLength,它允许我们检索不同路径长度的坐标。但是,我需要一种不同的行为,到目前为止我还没有找到解决方案。

我需要圆圈沿着路径动画,但是以稳定的水平速度。这意味着圈子应该花费相同的时间来导航这片:

slice1

与此切片一样:

slice2

因为两个切片都包含相同的宽度。在较低的层面上,我需要的是能够将任何X坐标转换为沿路径的相应Y坐标。我已经查看了所有SVG path methods,但我还没有找到任何特别有用的东西。我希望在D3中有某种方法可以将X坐标输入到d3线并检索其相应的Y坐标。

这里是JSFiddle,如上所述。我真的很感激我能得到的任何帮助。谢谢!

1 个答案:

答案 0 :(得分:2)

我最终使用getPointAtLength为该线上的所有点创建了一个查找数组:

var lookup = [];
var granularity = 1000;
var l = path.node().getTotalLength();
for(var i = 1; i <= granularity; i++) {
    var p = path.node().getPointAtLength(l * (i/granularity))
    lookup.push({
        x: p.x,
        y: p.y
    })
}

一旦我在查询表中获得了所有这些点,我在翻译补间中使用了一个平分线:

var xBisect = d3.bisector(function(d) { return d.x; }).left;
function translateAlong(path) {
    var l = path.getTotalLength();
    return function (d, i, a) {
        return function (t) {
            var index = xBisect(lookup, l * t);
            var p = lookup[index];
            return "translate(" + p.x + "," + p.y + ")";
        };
    };
}

它按预期工作!雅虎!

Fiddle