我将解释我在实际项目中遇到的问题。我正在使用一个Web服务,这会给我返回点x,y。我使用settimeout模拟Web服务。我想在这些坐标中放一个圆圈,对于每个圆圈,我想画一条连接它们的线。像这样:
我想在圆圈之间添加一条线但显示动画。像这样:
http://bl.ocks.org/duopixel/4063326
例如这个动画,但是逐点
当我运行我的应用程序时,我希望该行具有从初始循环到结束的动画。如果我添加一个新的圆圈,我想要创建一条线并为圆圈添加动画。我该怎么办?
var svg = d3.select('svg');
var dataSet = [10, 20, 30, 40];
function display(data){
var circle = svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr({
r:function(d){ return d },
cx:function(d, i){ return i * 100 + 50 },
cy:50,
fill: 'red'
});
}
display(dataSet);
setTimeout(function(){
display([5]);
},2000)
答案 0 :(得分:3)
回答如何连接点:
要创建连接圈子的路径,您只需创建一个使用相同数据的线路生成器。
例如,这将创建一个包含10个对象的数组,每个对象具有x
和y
位置:
var dataSet = d3.range(10).map(function(d) {
return {x: someValue, y: someValue}
});
因此,由于我们使用这些属性来定位圆圈,我们只在线条生成器中使用相同的属性:
var lineGenerator = d3.svg.line()
.x(function(d) {return d.x})
.y(function(d) {return d.y})
.interpolate("monotone")
然后,使用你链接的bl.ocks中的函数:
var totalLength = path.node().getTotalLength();
path.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
以下是演示:
var svg = d3.select('svg');
var backLayer = svg.append("g");
var frontLayer = svg.append("g");
var dataSet = d3.range(10).map(function(d) {
return {
x: d * 30 + 10,
y: Math.random() * 130 + 10
}
});
var lineGenerator = d3.svg.line()
.x(function(d) {
return d.x
})
.y(function(d) {
return d.y
})
.interpolate("monotone")
function displayCircles(data) {
var circle = frontLayer.selectAll(null)
.data(data)
.enter()
.append('circle')
.attr({
r: 6,
cx: function(d) {
return d.x
},
cy: function(d) {
return d.y
},
fill: 'white',
stroke: "black",
"stroke-width": "3px"
});
};
function displayLine(data) {
var line = backLayer.append("path")
.datum(data)
.attr({
d: lineGenerator(data),
fill: 'none',
stroke: "red",
"stroke-width": "3px",
"shape-rendering": "geometricPrecision"
});
var totalLength = line.node().getTotalLength();
line.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
}
displayCircles(dataSet);
setTimeout(function() {
displayLine(dataSet)
}, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg></svg>
答案 1 :(得分:0)
您的demo code向我们展示了一种非常智能的动画路径方式,我将使用attrTween提供另一种不同的解决方案:
var w = 500, h = 100;
var data = d3.range(100).map(function(d){
return Math.random() * 5 + 5;
});
var x = d3.scale.linear().domain([0, 50]).range([0, 500]);
var y = d3.scale.linear().domain([0, 10]).range([0, 100]);
var line = d3.svg.line()
.interpolate("cardinal")
.x(function(d,i) {return x(i);})
.y(function(d) {return y(d);})
var svg = d3.select("#container")
.append("svg")
.attr({ width: w, height: h })
.style("border", "1px solid #ccc")
.append("path")
.datum(data)
.attr({
d: line(data.slice(0,1)),
fill: "none",
stroke: "#CB6154",
"stroke-width": 2
})
.transition()
.duration(2000)
.attrTween("d", function(d){
var f = d3.interpolate(0,50);
return function(t){
return line(d.slice(0, Math.ceil(f(t))));
};
})
这是jsfiddle结果。