This example demonstrates controlling transitions separately in two groups of objects.
The two blocks are largely redundant - the intention is to show how arbitrary animations could be controlled on two distinct sets of objects using classes.
var svg = d3.select("svg"), | |
margin = {top: 40, right: 40, bottom: 40, left: 40}, | |
width = svg.attr("width") - margin.left - margin.right, | |
height = svg.attr("height") - margin.top - margin.bottom; | |
var g = svg.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
data1 = [ | |
[ | |
{'x': 200, 'y': 150, 'r': 12, 'color': 'blue'}, | |
{'x': 140, 'y': 83, 'r': 14, 'color': 'blue'}], | |
[ | |
{'x': 300, 'y': 190, 'r': 26, 'color': 'green'}, | |
{'x': 240, 'y': 123, 'r': 27, 'color': 'green'}]] | |
data2 = [ | |
[ | |
{'x': 500, 'y': 50, 'r': 30, 'color': 'red'}, | |
{'x': 400, 'y': 90, 'r': 40, 'color': 'red'}, | |
{'x': 440, 'y': 150, 'r': 34, 'color': 'red'}], | |
[ | |
{'x': 300, 'y': 200, 'r': 20, 'color': 'orange'}, | |
{'x': 290, 'y': 240, 'r': 25, 'color': 'orange'}, | |
{'x': 240, 'y': 300, 'r': 16, 'color': 'orange'}], | |
[ | |
{'x': 450, 'y': 260, 'r': 32, 'color': 'yellow'}, | |
{'x': 460, 'y': 320, 'r': 25, 'color': 'yellow'}, | |
{'x': 490, 'y': 360, 'r': 11, 'color': 'yellow'}]] | |
// create group1 circles | |
g.append('g') | |
.selectAll("circle") | |
.data(data1[0]) | |
.enter() | |
.append("circle") | |
.attr('class', 'circ1') | |
.attr('fill', function(d) { return d.color; }) | |
.attr('cx', function(d) { return d.x; }) | |
.attr('cy', function(d) { return d.y; }) | |
.attr('r', function(d) { return d.r; }); | |
// create group2 circles | |
g.append('g') | |
.selectAll("circle") | |
.data(data2[0]) | |
.enter() | |
.append("circle") | |
.attr('class', 'circ2') | |
.attr('fill', function(d) { return d.color; }) | |
.attr('cx', function(d) { return d.x; }) | |
.attr('cy', function(d) { return d.y; }) | |
.attr('r', function(d) { return d.r; }); | |
var current_state_1 = 0; | |
function update_circ1() { | |
// compute current iteration stage | |
current_state_1 = (current_state_1 + 1) % data1.length; | |
var transitions1 = 0; | |
d3.selectAll('.circ1') | |
// update data | |
.data(data1[current_state_1]) | |
// update radius over r*35 | |
.transition() | |
.delay(function(d) { return d.r * 7; }) | |
.duration(function(d) { return d.r * 35; }) | |
.attr('r', function(d) { return d.r; }) | |
// register the number of callbacks | |
.on('start', function() { transitions1++; }) | |
// update x, y, and fill over r*35 | |
.transition() | |
.duration(function(d) { return d.r * 35; }) | |
.attr('fill', function(d) { return d.color; }) | |
.attr('cx', function(d) { return d.x; }) | |
.attr('cy', function(d) { return d.y; }) | |
// wait for all to finish and then call update_circ1 again | |
.on('end', function() { | |
if( --transitions1 === 0 ) { | |
update_circ1(); | |
} | |
}); | |
} | |
var current_state_2 = 0; | |
function update_circ2() { | |
// compute current iteration stage | |
current_state_2 = (current_state_2 + 1) % data2.length; | |
var transitions2 = 0; | |
d3.selectAll('.circ2') | |
// update data | |
.data(data2[current_state_2]) | |
// change color and radius over r*10 | |
.transition() | |
.delay(function(d) { return 500; }) | |
.duration(function(d) { return d.r * 10; }) | |
.attr('r', function(d) { return d.r; }) | |
.attr('fill', function(d) { return d.color; }) | |
// register the number of callbacks | |
.on('start', function() { transitions2++; }) | |
// change x position over 5000/r | |
.transition() | |
.delay(function(d) { return 5000 / d.r; }) | |
.duration(function(d) { return d.r * 25; }) | |
.attr('cx', function(d) { return d.x; }) | |
// change y position over 5000/r | |
.transition() | |
.delay(function(d) { return 5000 / d.r; }) | |
.duration(function(d) { return d.r * 25; }) | |
.attr('cy', function(d) { return d.y; }) | |
// wait for all to finish and then call update_circ2 again | |
.on('end', function() { | |
if( --transitions2 === 0 ) { | |
update_circ2(); | |
} | |
}); | |
} | |
update_circ1(); | |
update_circ2(); |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<svg width="760" height="500"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="grouped.js"></script> |