使用svg和d3在圆和线之间转换

时间:2013-04-20 13:34:59

标签: svg d3.js

JS Fiddle

我正在试图弄清楚如何解开" /"解开"通过"剪切"它在顶部,然后它会动画到一条线。

我通过使用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   }   ];

1 个答案:

答案 0 :(得分: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)
}

Here is the jsFiddle,您只需点击节点即可查看动画。

需要注意的一件重要事情是,每个点的转换需要相同的时间,而实际上,您希望最终的点在中间附近的点之后到达。您可以使用的技巧是使动画的持续时间与从源点到目标点的距离成比例但我没有看到如何在传递整个数组时使用它,这样您就无法更改持续时间特定点。