1

JS小提琴

我试图弄清楚如何通过在顶部“剪断”它来“展开”/“解开”一个圆圈,然后它会动画成一条线。

我用 16 个点做了一个圆(用第 17 个点来关闭它,因为如果我使用封闭插值,过渡看起来会很奇怪)

如何(将通过动画?,只需调整 x 和 y 点?,另一种插值?)您可以一次在圆和线之间转换一个点吗?

圆点:

//The data for our line
var circleData = [ { "x": 150 , "y": 20   },
                 { "x": 165.30, "y": 23.04},
                 { "x": 178.28, "y": 31.71},
                 { "x": 186.95, "y": 44.69},
                 { "x": 190   , "y": 60   },
                 { "x": 186.95, "y": 75.30},
                 { "x": 178.28, "y": 88.28},
                 { "x": 165.30, "y": 96.95},
                 { "x": 150   , "y": 100   },
                 { "x": 134.69, "y": 96.95},
                 { "x": 121.71, "y": 88.28},
                 { "x": 113.04, "y": 75.30},
                 { "x": 110   , "y": 60.00},
                 { "x": 113.04, "y": 44.69},
                 { "x": 121.71, "y": 31.71},
                 { "x": 134.69, "y": 23.04},
                 { "x": 150   , "y": 20   }   ];

线点:

var lineData = [ { "x": 10    , "y": 200   },
                 { "x": 20    , "y": 200   },
                 { "x": 30    , "y": 200   },
                 { "x": 40    , "y": 200   },
                 { "x": 50    , "y": 200   },
                 { "x": 60    , "y": 200   },
                 { "x": 70    , "y": 200   },
                 { "x": 80    , "y": 200   },
                 { "x": 90    , "y": 200   },
                 { "x": 100   , "y": 200   },
                 { "x": 110   , "y": 200   },
                 { "x": 120   , "y": 200   },
                 { "x": 130   , "y": 200   },
                 { "x": 140   , "y": 200   },
                 { "x": 150   , "y": 200   },
                 { "x": 160   , "y": 200   },
                 { "x": 170   , "y": 200   }   ];
4

1 回答 1

2

在尝试 Duopixel 的演示时,我注意到的第一件事是圆圈似乎缩小以适合在线。因此,我决定让这条线与圆的长度相同。此外,为了获得均匀分布,我编写了两个函数来创建线和圆数据数组:

var numberOfPoints = 30;
var radius = 60
var margin = {top: 20,left: 20}
var lineLength = 2 * radius * Math.PI

var circleData = $.map(Array(numberOfPoints), function (d, i) {
    var imag = margin.left + lineLength / 2 + radius * Math.sin(2 * i * Math.PI / (numberOfPoints - 1))
    var real = margin.top + radius - radius * Math.cos(2 * i * Math.PI / (numberOfPoints - 1))
    return {x: imag, y: real}
})

var lineData = $.map(Array(numberOfPoints), function (d, i) {
    var y = margin.top + 2 * radius;
    var x = margin.left + i * lineLength / (numberOfPoints - 1)
    return { x: x, y: y}
}).reverse()

那么,现在,我们可以应用什么效果呢?我将使用最简单的一种:将圆的每个点映射到线上的点的过渡。

var circle = svgContainer.append("g")
    .append("path")
    .data([circleData])
    .attr("d", lineFunction)
    .attr("class", "circle")
    .on("click", transitionToLine)

function transitionToLine() {
    circle.data([lineData])
        .transition()
        .duration(1000)
        .ease("linear")
        .attr('d', lineFunction)
    circle.on("click", transitionToCircle)
}
function transitionToCircle() {
    circle.data([circleData])
        .transition()
        .duration(1000)
        .ease("linear")
        .attr('d', lineFunction)
    circle.on("click", transitionToLine)
}

这是 jsFiddle,您只需单击节点即可查看动画。

需要注意的一件重要事情是,每个点的转换花费相同的时间,而实际上您希望最后的点在靠近中间的点之后到达。您可以使用的技巧是使动画的持续时间与从源点到目标点的距离成正比,但是当您传递整个数组时,我看不到如何将其与线条一起使用,因此您无法更改持续时间对于一个特定的点。

于 2013-04-21T00:08:59.873 回答