JSFiddle - React, Tailwind, and code Playground

by dirtyd77

HTML

<svg id="svg">
    <defs>
        <pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
        <image xlink:href="http://stockmarketadvantage.com/wp-content/uploads/2014/02/Tom-DeMark.jpg" x="0" y="0" width="100" height="100" />
         
    </pattern>
        
        <pattern id="img2" patternUnits="userSpaceOnUse" width="100" height="100">
            <image xlink:href="http://stockmarketadvantage.com/wp-content/uploads/2014/05/Tom-DeMark-May-2014.jpg" x="0" y="0" width="100" height="100" />   
     </pattern>
    </defs>
</svg>

CSS

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
circle {
  fill: black;
  stroke: none;
}

circle.exiting {
  fill: url(#img1);
  stroke: none;
}
circle.saved {
  fill: url(#img2);
}

JavaScript

var w = 900,
    h = 500,
    svg = d3.select('#svg')
      .attr('width',w)
      .attr('height',h);
 
var data = [],
    removed = [];
 
function render() {
 
  var circles = svg.selectAll('circle')
    .data(data, function(d){
      return d.id;
    });
 
  circles.enter().append('circle')
    .classed('entering',true)
     
    .attr('cx',function(d){ return d.center.x; })
    .attr('cy',function(d){ return d.center.y; })
    .attr('r', 100)
    .style('opacity',1e-6);
 
  circles.exit().filter(':not(.exiting)') // but only if we didn't already
    .classed('exiting',true)
      .transition()
      .duration(250)
    .attr('r', 100)
    .style('opacity',1e-6)
    .remove();
 
  circles.classed('saved',function(d){ return d.saved; });
 
  circles.filter('.exiting, .entering')
    .classed('exiting',false)
    .classed('entering',false)
  .transition()
  .duration(200)
    .attr('r',function(d){ return d.radius; })
    .style('opacity',1.0);
 
}
 
setInterval(function(){
  if (data.length > 20 && Math.random() > 0.5) {
    var index = Math.floor(Math.random() * data.length);
    var item = data[index];
    data.splice(index,1);
    if (Math.random() < 0.25) {
      item.saved = true;
      removed.push(item);
    }
  } else {
    if (removed.length) {
      data.push(removed.pop());
    } else {
      data.push({
        id: new Date().getTime(),
        center: {
          x: Math.random() * w,
          y: Math.random() * h
        },
        radius: 2 + Math.random() * 10
      });
    }
  }
  render();
}, 10);