<div class="help">mouse down to emit</div>
<div class="smokeOuterWrap">
<div class="blobs" id="blobWrap">
</div>
</div>
@import "compass/css3";

.help {
  margin: 15px;
}
.smokeOuterWrap {
  border: 1px solid #ccc;
  overflow: hidden;
}
.blobs{
  position:relative;
  top:0;
  left:0;
  bottom:0;
  right:0;
  width:600px;
  background: white;
  height:350px;
  margin:auto;
  -webkit-filter:blur(5px) contrast(10);
  filter:blur(12px) contrast(30);
}

.blob{
  background:#000;
  height:40px;
  position:absolute;
  top:100%;
  margin-top:-20px;
  margin-left:-20px;
  border-radius:100%;
}
$rate = 50;
$duration = 4;
$blobMaxNum = 200;
$particleSz = 40;
$variance = 10;
$wind = 50;

$blobCount = 0;
$blobID = 0;
$blobs = new Array();
$itv = null;  // Interval

// Smoke wrapper
var $wr = document.getElementById('blobWrap');
window.addEventListener ("mousedown", function () {
  $itv = setInterval(newBlob, $rate);
});

window.addEventListener ("mouseup", function () {
  // console.log("clear");
  clearInterval($itv);
});

function newBlob()
{
  if($blobs.length < $blobMaxNum)
  {  
    var b = new Blob();
    
      $wr.appendChild(b.element);
    
      $blobs.push(b);
    
      // console.log(b.currentLeft + " to " + b.targetLeft);
    
    // Variance
    var $durV = rndBtw(5, 30) / 10;
    
      TweenMax.to(b, $duration +$durV, { currentTop:b.targetTop, ease:Power3.easeOut });  
      TweenMax.to(b, $duration +$durV, { currentLeft:b.targetLeft, ease:Elastic.easeOut });
      TweenMax.to(b, $duration +$durV, { currentSize: 0 });
      TweenMax.to(b, $duration +$durV, { onUpdate: moveBlobs, onComplete:killBlob, onCompleteParams:[b] });
      $blobCount++;    
      
    // console.log($('.blobs').innerHTML());
  }
}

function killBlob($b)
{
  var $el = document.getElementById($b.ref);
  $el.parentNode.removeChild($el);
  
  // console.log("kill" + $el);
  
  // $('#' + $b.ref).remove();
  
  $blobs.splice($blobs.indexOf($b), 1);
  
  // console.log($blobs.length);
}
 
function moveBlobs()
{
  for(var i = 0; i < $blobs.length; i++)
    {
      var b = $blobs[i];
      var bh = document.getElementById(b.ref);
      // console.log("---");
      // console.log( b.currentLeft );
      bh.style.top = b.currentTop + "%";
      bh.style.left = b.currentLeft + "%";
      bh.style.width = b.currentSize + "px";
      bh.style.height = b.currentSize + "px";
    }
}

function Blob()
{  
  $sz = rndBtw($particleSz - $variance, $particleSz + $variance);
  $wid = ($sz * 2) + "px";
  $ht = $sz + "px";  
  $left = "50%";
   
  $div = document.createElement('div');
  $div.setAttribute('id', 'blob' + $blobID);
  $div.style.width = $wid;
  $div.style.height = $ht;
  $div.style.left = $left;
  $div.className += "blob";
  
  $tL = rndBtw(44,56);
  
  this.ref = "blob" + $blobID;
  this.index = $blobs.length;
  this.element = $div;  
  this.currentTop = 100;
  this.currentLeft = 50;
  this.targetTop = 10;
  this.targetLeft = $tL;
  this.currentSize = $sz;
  
  $blobID++;
}

function rndBtw($min, $max)
{
  // console.log("betweeen" + $min + " / " + $max);
  return Math.floor(Math.random() * ($max - $min + 1)) + $min;
  // return Math.floor(Math.random() * $max) + $min;
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js