Noisy Nipple

Experiment on Audio API and Raphael.js

by Serkan Yersen

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script>
<div id="canvas"></div>

<div class="warning"><svg height="32px" style="enable-background:new 0 0 32 32;" version="1.1" viewBox="0 0 32 32" width="32px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="_x38__audio_headphones"><g><path d="M25.773,15.927c-0.014-0.004-0.027-0.012-0.041-0.017v-1.004c0-5.359-4.361-9.722-9.722-9.722s-9.722,4.362-9.722,9.722    v0.996v10.61c0.569,0.193,1.177,0.305,1.812,0.305c0.184,0,0.366-0.012,0.546-0.029v-4.516v-6.617h0.209    c-0.069-0.009-0.14-0.008-0.209-0.016v-0.733c0-4.061,3.304-7.364,7.365-7.364c4.062,0,7.364,3.303,7.364,7.364v0.731    c-0.076,0.008-0.154,0.007-0.23,0.018h0.209v11.133c0.18,0.018,0.363,0.029,0.547,0.029c0.656,0,1.287-0.119,1.873-0.328V15.927z"/><path d="M5.028,16.537c-1.522,1.002-2.537,2.711-2.537,4.67c0,1.961,1.01,3.688,2.537,4.689V16.537z"/><path d="M27.033,16.577v9.283c1.494-1.008,2.477-2.717,2.477-4.652C29.51,19.273,28.521,17.584,27.033,16.577z"/></g></g></svg>
Beware! This demo has sound! 
</div>

SCSS

html, body {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  font-family: Helvetica, Ariel, sans
}

#canvas {
  height: 100%;
  width: 100%;
  background: #dddddd;
}

.warning {
  position: absolute;
  top: 10px;
  right: 10px;
  background: white;
  padding: 10px;
  line-height: 32px;
}
.warning svg {
  vertical-align: bottom;
}

JavaScript

$.extend($.easing, {
      elastic: function (x, t, b, c, d) {
        var s=1.70158;var p=0;var a=c;
        if (t===0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*0.3;
        if (a < Math.abs(c)) { a=c; s=p/4; }
        else{ s = p/(2*Math.PI) * Math.asin (c/a); }
        return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
      }
    });

    Raphael.st.draggable = function(options) {
      options = options || {};

      var me = this,
          lx = 0,
          ly = 0,
          ox = 0,
          oy = 0,
          moveFnc = function(dx, dy) {
              lx = dx + ox;
              ly = dy + oy;
              me.transform('t' + lx + ',' + ly);
              options.onMove(lx, ly);
          },
          startFnc = function() {
            options.onStart();
          },
          endFnc = function() {
              ox = 0;
              oy = 0;
              options.onEnd(me, lx, ly);
          };

      this.drag(moveFnc, startFnc, endFnc);
    };


    $(function() {

      window.AudioContext = window.AudioContext || window.webkitAudioContext;
      var ctx = new AudioContext(), currentOsc, isMouseDown, lastY;

      var getFreq = function(x, y){
        if(x === 0){
          return 0;
        }
        if(y === 0){
          return 0;
        }

        return ((Math.abs(x)) + (Math.abs(y))) * 5;
      };
      
      var moveCircles = function(x, y){
        circles.forEach(function(c, i){
          var m = Number('0.'+i);
          c.transform('t' + (x * m) + ',' + (y*m));
        });
      };
      
      var paper = Raphael(document.getElementById('canvas'));
      var mySet = paper.set();

      var h = $('body').height();
      var w = $('body').width();
      var centerX = '50%';
      var centerY = '50%';

      var circles = [
        paper.circle(centerX, centerY, '35%').attr({'fill': '#2ECC40', 'stroke': ''}),
        paper.circle(centerX, centerY, '30%').attr({'fill': '#3D9970', 'stroke': ''}),
       ...