block by harrystevens a328dcdf96f93cdc152b168bd21c34bc

Gooey Cell Division

Full Screen

You can do interesting things with data joins and updating data in D3.js I took the gooey effect from Nadieh Bremer’s block.

index.html

<html>
  <head>
    <style>
    body {
      margin: 0;
      background: #3a403d;
    }
    .amoeba {
      fill: #fff;
    }
    </style>
  </head>
  <body>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    <script>
    var width = window.innerWidth,
      height = window.innerHeight;

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height)
        .style("filter", "url(#gooey)"); //Set the filter on the container svg;

    var data = [{group: 1, id: 1, x: width / 2, y: height / 2}];

    //SVG filter for the gooey effect
    //Code taken from //bl.ocks.org/nbremer/69808ec7ec07542ed7df
    var defs = svg.append("defs");

    var filter = defs.append("filter").attr("id", "gooey");
    filter.append("feGaussianBlur")
      .attr("in", "SourceGraphic")
      .attr("stdDeviation", "10")
      .attr("result", "blur");
    filter.append("feColorMatrix")
      .attr("in", "blur")
      .attr("mode", "matrix")
      .attr("values", "1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7")
      .attr("result", "gooey");
    filter.append("feComposite")
      .attr("in", "SourceGraphic")
      .attr("in2", "gooey")
      .attr("operator", "atop");

    function redraw(data){

      // transition
      var t = d3.transition()
          .duration(1500);

      //JOIN
      var amoeba = svg.selectAll(".amoeba")
        .data(data, function(d){ return d.id; });

      // EXIT
      amoeba.exit().remove();

      // UPDATE
      amoeba
        .transition(t)
          .attr("cx",function(d){ return d.x; })
          .attr("cy",function(d){ return d.y; });

      // ENTER
      amoeba.enter().append("circle")
          .attr("class", "amoeba")
          .attr("r", 50)
          .attr("cx",function(d){ return d.x; })
          .attr("cy",function(d){ return d.y; });
    }

    redraw(data);


    function run(){
      setTimeout(function(){
        data.forEach(function(d){
          data.push({group: 1, id: data.length + d.id, x: d.x, y: d.y});
        });
        redraw(data);
      }, 750)

      setTimeout(function(){
        data.forEach(function(d, i){
          data[i] = {group: d.group, id: d.id, x: width * (d.id / (data.length + 1)), y: d.y};
        });
        redraw(data);
      }, 1500);

      setTimeout(function(){
        data.forEach(function(d, i){
          data.push({group: d.group, id: data.length + 1, x: d.x, y: d.y});
        });
        redraw(data);
      }, 3000);

      setTimeout(function(){
        data.forEach(function(d, i){
          d.group = i < 2 ? 1 : 2;
          data[i] = {group: d.group, id: i + 1, x: d.x, y: height * (d.group / 3)};
        });
        redraw(data);
      }, 3750);

      setTimeout(function(){
        data.forEach(function(d, i){
          data[i] = {group: d.group, id: i + 1, x: d.x, y: height / 2};
        });
        redraw(data);
      }, 6000);

      setTimeout(function(){
        data.forEach(function(d, i){
          data[i] = {group: d.group, id: d.id, x: width / 2, y: d.y}
        });
        redraw(data.splice(2, 2));
      }, 8000);

      data = [{group: 1, id: 1, x: width / 2, y: height / 2}];
    }

    run();

    d3.interval(run, 9000);
    </script>
  </body>
</html>