Animation 使用D3.js沿连续路径插值
我正在修改Mike Bostock的模型,以接受n条单独路径的数组,并沿每条路径连续插值。由于D3相对较新,下面的代码显示了我所掌握的,即同时为两条路径运行点插值。现在,我有点纠结于如何重新构造它,使过程连续(只有一个移动对象)。实际上,我需要能够在路径之间停下来听鼠标点击,但一旦结构出现,我就可以找出代码。非常感谢您的帮助 这是我的建议 子孙后代的代码:Animation 使用D3.js沿连续路径插值,animation,d3.js,Animation,D3.js,我正在修改Mike Bostock的模型,以接受n条单独路径的数组,并沿每条路径连续插值。由于D3相对较新,下面的代码显示了我所掌握的,即同时为两条路径运行点插值。现在,我有点纠结于如何重新构造它,使过程连续(只有一个移动对象)。实际上,我需要能够在路径之间停下来听鼠标点击,但一旦结构出现,我就可以找出代码。非常感谢您的帮助 这是我的建议 子孙后代的代码: <!DOCTYPE html> <meta charset="utf-8"> <body>
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<style>
path {
fill: none;
stroke: #000;
stroke-width: 3px;
}
circle {
stroke: #fff;
stroke-width: 3px;
}
</style>
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script><script>
var pathdata = [
[[240, 100],
[290, 200],
[340, 50]],
[[340, 50],
[90, 150],
[140, 50],
[190, 200]]
];
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 500);
var paths = svg.selectAll("path")
.data(pathdata)
.enter()
.append("path")
.attr("d", d3.svg.line())
.attr("id",function(d, i) { return "path" + i });
// plot path vertices
svg.selectAll(".point")
.data([].concat.apply([], pathdata))
.enter().append("circle")
.attr("r", 5)
.attr("fill", "red")
.attr("transform", function(d) { return "translate(" + d + ")"; });
// interpolate along path0
var circle = svg.append("circle")
.attr("r", 10)
.attr("fill", "steelblue")
.attr("transform", "translate(" + pathdata[0][1] + ")")
.transition()
.duration(4000)
.attrTween("transform", translateAlong(d3.select("#path0")[0][0]));
// interpolate along path1
var circle = svg.append("circle")
.attr("r", 10)
.attr("fill", "steelblue")
.attr("transform", "translate(" + pathdata[1][1] + ")")
.transition()
.duration(4000)
.attrTween("transform", translateAlong(d3.select("#path1")[0][0]));
function translateAlong(path) {
console.log(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 + ")";
};
};
}
</script>
</body>
</html>
或者
创建一个函数,该函数将d3路径选择和路径(在选择中)的整数索引作为参数,并沿该路径设置动画。此函数在该选择中找到适当的路径,沿该路径启动一个圆的过渡,并订阅该过渡的
'end'
事件,在该点触发下一个动画
附言
我不会像您建议的那样重新构造数据,因为您需要有不同的SVG
元素——序列中的每个“章节”对应一个元素。正如您现在所做的那样,每个路径都有一个不同的数组,这使您能够通过data()
绑定创建这些
s
根据您试图实现的目标,您甚至可能希望进一步嵌套每个路径数组,用对象{}
包装它,以保存有关路径的元数据:
var pathData = [
{
name: "Crossing the Niemen",
points: [ [240, 100], [290, 200], [340, 50] ]
},
{
name: "March on Vilnius",
points: [ [340, 50], [90, 150], [140, 50], [190, 200] ]
},
{
name: "March on Moscow",
points: [ [190, 200], [70, 180], [30, 30], [350, 160] ]
}
];
谢谢Meetam,这非常有帮助。我怀疑它可能涉及一个新的功能。关于数据格式的有用提示。@geotheory当然。这是一个需要解决的有趣问题。另外,看起来你在做一些不错的研究工作。
// 3rd field for interpolation end-points
var points_alt2 = [
[240, 100, 0],
[290, 200, 0],
[340, 50, 1],
[340, 50, 0],
[90, 150, 0],
[140, 50, 0],
[190, 200, 1]
]
function animateSinglePath(selection, indexOfAnimated) {
indexOfAnimated = indexOfAnimated || 0;
// Create circle if doesn't already exist
// (achived by binding to single element array)
circle = svg.selectAll('.animated-circle').data([null])
circle.enter()
.append("circle")
.attr("class", "animated-circle")
.attr("r", 10)
.attr("fill", "steelblue")
selection.each(function(d, i) {
// find the path we want to animate
if(i == indexOfAnimated) {
// In this context, the "this" object is the DOM
// element of the path whose index, i equals the
// desired indexOfAnimated
path = d3.select(this)
// For style, make it dashed
path.attr('stroke-dasharray', '5, 5')
// Move circle to start pos and begin animation
console.log('Start animation', i)
circle
.attr("transform", "translate(" + d[0] + ")")
.transition()
.duration(2000)
.attrTween("transform", translateAlong(path.node()))
.each('end', function() {
console.log('End animation', i);
// For style, revert stroke to non-dashed
path.attr('stroke-dasharray', '')
// trigger the next animation by calling this
// function again
animateSinglePath(selection, indexOfAnimated + 1);
});
}
});
}
var pathData = [
{
name: "Crossing the Niemen",
points: [ [240, 100], [290, 200], [340, 50] ]
},
{
name: "March on Vilnius",
points: [ [340, 50], [90, 150], [140, 50], [190, 200] ]
},
{
name: "March on Moscow",
points: [ [190, 200], [70, 180], [30, 30], [350, 160] ]
}
];