<div id="hose"></div>
html {
  background: #1d1d1d;
}

body,
html {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

body { &:hover { cursor: pointer; } }

#hose {
  position: relative;
}

.bubble {
  background: radial-gradient(ellipse at center, #86CC01 0%,#bee96b 100%);
  border-radius: 80%;
  position: absolute;
  transform-origin: center center;
}
// via Jack Doyle:
// If you want something that’s the MOST performant, you might wanna create 
// and pre-populate a couple of timelines that you can toggle between, 
// as demonstrated here: https://codepen.io/GreenSock/pen/nkylt
//
// This way, when someone clicks, there’s no effort in creating tweens or 
// instantiating values – it’s already done and you just restart() the timeline. 
// Super fast.

var hose            = document.getElementById('hose'),
    tub             = document.createElement('div'),
    tub_size        = 100,
    bubble_count    = 40,
    bubble_size_max = 50,
    bubble_size_min = 20,
    speed           = 2,
    gravity         = 2;

TweenLite.set(hose, {
  width: tub_size,
  height: tub_size
});

// 'bubbler' is a TimelineLite instance
var bubbler = createBubbles(tub);

function createBubbles(tub) {
  var tmax_tl = new TimelineMax(),
      angle,
      length,
      dot,
      i,
      size;
  
  $('.bubble').remove();

  // Bubble Maker
  for (i = 0; i < bubble_count; i++) {
    bubble = document.createElement('b');
    
    bubble.className = 'bubble';

    size = randomBubbles(bubble_size_min, bubble_size_max);

    tub.appendChild(bubble);

    angle = Math.random() * 360; // random angle
    
    length = Math.random() * (tub_size / 2 - size / 2);

    TweenLite.set(bubble, {
     	 x: 0,
     	 y: 0,
      width: size,
      height: size,
      force3D: true
    });

    // Bubble's Animation
    tmax_tl.to(bubble, 1 + Math.random(), {
      opacity: 0,
      physics2D: {
        angle: angle,
        velocity: (100 + Math.random() * 250) * speed, // init. velocity
        gravity: 1200 * gravity // +/- to give gravity +/- pull
      }

      // Use the following lines instead of physics2D:
      // x: Math.cos(angle) * length * 6,
      // y: Math.sin(angle) * length * 6
    }, 0);
  }

  return tmax_tl;
}

function spitBubbles(element) {
  element.appendChild(tub);
}

function randomBubbles(min, max) {
  return min + Math.random() * (max - min);
}

function bubbleMaker(e) {
  // Natural Movement
  createBubbles(tub);

  // addPause example
  // createBubbles(tub).addPause(0.25);

  spitBubbles(hose);

  TweenLite.to(hose, 0, {
    x: e.pageX,
    y: e.pageY
  });
}

$(window).on('mousedown', bubbleMaker);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/gsap/1.16.0/TweenMax.min.js
  3. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/Physics2DPlugin.min.js