JSFiddle - React, Tailwind, and code Playground

by Dogbert

HTML

<script src="https://d3js.org/d3.v4.js"></script>

CSS

html {
  height: 100%;
}

body {
  background: white;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  margin: 0;
}

svg {
  border: 1px solid black;
}

circle {
  fill: rgba(28, 144, 243, 0.6);
}

JavaScript

function rand(start, end) {
  return start + ~~(Math.random() * (end + 1 - start));
}

function gen() {
  return d3.range(rand(5, 15)).map(function() {
    return {
      x: rand(40, 360),
      y: rand(40, 360),
      r: rand(8, 40),
      key: rand(0, 20)
    };
  });
}

var svg = d3.select("body").append("svg");
svg.attr("width", 400).attr("height", 400);

tick();

function tick() {
  const duration = 2000;
  var circle = svg.selectAll("circle")
    .data(gen(), (d) => d.key);

  circle.exit()
    .transition()
    .duration(duration / 2)
    .attr("r", 0)
    .delay((d, i) => i * 50)
    .remove();

  circle = circle.enter()
    .append("circle")
    .attr("cx", (d) => d.x)
    .attr("cy", (d) => d.y)
    .attr("r", 0)
    .merge(circle);

  circle.transition()
    .ease(d3.easeExpOut)
    .duration(duration)
    .delay((d, i) => i * 50)
    .attr("cx", (d) => d.x)
    .attr("cy", (d) => d.y)
    .attr("r", (d) => d.r);

  circle.on("mouseover", function() {
    d3.select(this).style("fill", "steelblue");
  });

  setTimeout(tick, duration);
}