|
|
1
Andrew Reid
7 年前
实现这一点的方法有很多种。正如在另一个答案中所指出的,使用函数来实现这一点将使代码保持紧凑。就我个人而言,我倾向于使用transition的end事件来触发transition函数中的下一个transition。
这类函数的一般形式如下:
function transition() {
// .... optional logic here.
d3.select(this) // do transition:
.transition()
.attr("fill", ... )
.on("end", transition); // and repeat.
}
它可以用
selection.each(transition)
管理循环中当前颜色/过渡的一种方法是使用自定义属性。下面我用
.attr("i")
要跟踪:
var data = [
["orange","purple","blue","yellow"],
["blue","yellow","orange","purple"]
];
var svg = d3.select("svg");
var circles = svg.selectAll()
.data(data)
.enter()
.append("circle")
.attr("r", 20)
.attr("cx", function(d,i) { return i * 50 + 50; })
.attr("cy", 50)
.attr("fill", function(d) { return d[0]; })
.attr("i",0)
.each(transition);
// cycle endlessly:
function transition() {
var selection = d3.select(this);
// keep track of current value:
var i = selection.attr("i")
selection
.attr("i",i = ++i%4)
.transition()
.duration(1000)
.attr("fill", function(d) { return d[i] })
.on("end", transition);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
<svg width="500" height="300"></svg>
如果变换的顺序(起点)不同,则可以稍微修改上述方法:
var data = [50,75,100,125,150,175,200,225];
var colors = ["orange","purple","blue","yellow"];
var svg = d3.select("svg");
var circles = svg.selectAll()
.data(data)
.enter()
.append("circle")
.attr("r", 20)
.attr("cx", function(d) { return d; })
.attr("cy", 50)
.attr("fill", function(d,i) { return colors[i%4]; }) // set start fill
.attr("i", function(d,i) { return i%4; }) // record start position.
.each(transition);
function transition() {
var selection = d3.select(this);
var i = selection.attr("i");
i = ++i%colors.length;
selection.transition()
.duration(1000)
.attr("i",i)
.attr("fill", colors[i])
.on("end", transition);
}
<脚本src=“https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js“></脚本>
<svg width=“500”height=“300”></svg>
第一个我使用颜色集作为基准,第二个我只使用位置访问颜色
i
上述方法使用自定义属性,但我们也可以使用数据。这让我们在某些方面更加熟悉D3。
function transition() {
d3.select(this).transition()
.duration(1000)
.attr("fill", function(d) { return colors[++d.color%colors.length]; })
.on("end", transition);
}
var data = d3.range(8).map(function(d) { return {x: d*25+50}; })
var colors = ["orange","purple","blue","yellow"];
var svg = d3.select("svg");
var circles = svg.selectAll()
.data(data)
.enter()
.append("circle")
.attr("r", 20)
.attr("cx", function(d) { return d.x; })
.attr("cy", 50)
.attr("fill", function(d,i) { return colors[i%4]; }) // set start fill
.each(function(d,i) { d.color = i%4; }) // record start position.
.each(transition);
function transition() {
d3.select(this).transition()
.duration(1000)
.attr("fill", function(d) { return colors[++d.color%colors.length]; })
.on("end", transition);
}
<
如果您希望变换重复x次,甚至所有变换都以相同的颜色结束,我们也可以通过向基准添加一个新属性来跟踪完成的循环,从而相当容易地做到这一点:
var data = d3.range(8).map(function(d) { return {x: d*25+50}; })
var colors = ["orange","purple","blue","yellow"];
var svg = d3.select("svg");
var circles = svg.selectAll()
.data(data)
.enter()
.append("circle")
.attr("r", 20)
.attr("cx", function(d) { return d.x; })
.attr("cy", 50)
.attr("fill", function(d,i) { return colors[i%4]; }) // set start fill
.each(function(d,i) { d.color = d.start = i%4; }) // record start position.
.each(transition);
var n = 8; // n cycles
function transition() {
d3.select(this).transition()
.duration(1000)
.attr("fill", function(d) { return colors[++d.color%colors.length]; })
.on("end", function(d) { if(d.color - d.start < n) transition.apply(this); else return null; });
}
<脚本src=“https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js“></脚本>
<svg width=“500”height=“300”></svg>
有一些更懒惰的方法可以破坏性地修改数据(或部分数据),例如在这个只能运行一次的转换周期中使用shift:
var data = [
["orange","purple","blue","yellow"],
["blue","yellow","orange","purple"]
];
var svg = d3.select("svg");
var circles = svg.selectAll()
.data(data)
.enter()
.append("circle")
.attr("r", 20)
.attr("cx", function(d,i) { return i * 50 + 50; })
.attr("cy", 50)
.attr("fill", function(d) { return d.shift(); })
.each(transition);
function transition() {
var selection = d3.select(this);
if(selection.datum().length) {
selection.transition()
.duration(1000)
.attr("fill", function(d) { return d.shift() })
.on("end", transition);
}
}
<脚本src=“https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js“></脚本>
<svg width=“500”height=“300”></svg>
您可能会看到,我的代码段中没有一个使用子选择器:这可以通过自定义属性、数据属性或更简单地使用
.attr("fill",function(d,i){
|