JSFiddle - React, Tailwind, and code Playground

by Luis Lebolo

HTML

<script src="http://d3js.org/d3.v3.js"></script>
<div id="svgContainer"></div>

JavaScript

// Create dictionary of locks
var locks = {};

// Create SVG
var svg = d3.select('#svgContainer').append('svg')
.attr({
    width: 640,
    height: 480
});

// Create circles
svg.append("circle")
    .attr({
        id: 0,
        class: "circ big red",
        cx: 100,
        cy: 150,
        r: 50
    })
    .style("fill", "red");

svg.append("circle")
    .attr({
        id: 1,
        class: "circ big blue",
        cx: 300,
        cy: 250,
        r: 50
    })
    .style("fill", "blue");

svg.append("circle")
    .attr({
        id: 2,
        class: "circ small red",
        cx: 500,
        cy: 350,
        r: 25
    })
    .style("fill", "red");

/**
 * Transition handler
 */
function trans(selection, label, duration, apply) {
    selection.each(function() {
        // Interrupt if no current transition or if the labels match
        var interrupt = !this.__transition__ || !locks[this.id] || locks[this.id].active == label
        if (interrupt) {
            locks[this.id] = d3.select(this).transition();
        } else {
            locks[this.id] = locks[this.id].transition();
        }

        locks[this.id].ease('linear').duration(duration).call(apply);
        locks[this.id].active = label;
    });
}

// First transition
d3.selectAll('.red').call(trans, 'first', 4000, function(selection) {
    selection.style({
        stroke: 'black',
        'stroke-width': '40px'
    });
});

// Second transition
d3.selectAll('.big').call(trans, 'second', 4000, function(selection) {
    selection.style({
        stroke: 'white',
        'stroke-width': '10px'
    });
});

// Third transition (delayed)
setTimeout(function() {
    //d3.selectAll('.red').call(trans, 'third', 100, function(selection) { // Chain
    d3.selectAll('.red').call(trans, 'second', 100, function(selection) { // Interrupt
        selection.style({
            stroke: 'yellow',
            'stroke-width': '80px'
        });
    });
}, 6000);