<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/addons/p5.dom.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/13.2.0/Tone.min.js"></script>
  <link rel="stylesheet" type="text/css" href="style.css">
  <meta charset="utf-8" />

</head>

<body>
  <script src="sketch.js"></script>
</body>

</html>
html, body {
  margin: 0;
  padding: 0;
}
let bubbles = [],
  synth,
  sampleDraw,
  playRate;

function setup() {
  createCanvas(600, 400);
  for (let i = 0; i < 10; i++) {
    let x = random(width);
    let y = random(height);
    let r = random(20, 60);
    let b = new Bubble(x, y, r);
    bubbles.push(b);
  }
  bubbles.forEach(e => e.initSound());
}

function draw() {
  background(0);
  for (let i = 0; i < bubbles.length; i++) {
    bubbles[i].rollover(mouseX, mouseY);
    bubbles[i].move();
    bubbles[i].show();
  }
}

class Bubble {
  constructor(x, y, r) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.brightness = 0;
    this.isClicked = false;
  }

  rollover(px, py) {
    let d = dist(px, py, this.x, this.y);
    if (d < this.r) {
      // boolean flag
      // use for anytime you want somethign to only happen once
      // if the mouse is pressed set clicked to true
      // directly after the mouse is pressed set it to false to remove double triggers
      if (mouseIsPressed && !this.isClicked) {
        // switch the boolean so we don't get 
        // double triggers
        // we need this since mouseIsPressed will 
        // happen continuously in the draw loop
        this.isClicked = true;
        console.log(this.isClicked);
        this.playSound();
      }

      this.brightness = 255;
    } else {
      // reset the boolean flag when we move
      // off the circle 
      if (this.isClicked) {
        this.isClicked = false;
      }

      this.brightness = 0;
    }
  }

  move() {
    this.x = this.x + random(-2, 2);
    this.y = this.y + random(-2, 2);
  }

  show() {
    stroke(255);
    strokeWeight(4);
    fill(this.brightness, 125);
    ellipse(this.x, this.y, this.r * 2);
  }

  initSound() {
    this.synth = new Tone.Synth().toMaster();
  }

  playSound() {
    // console.log(this.x);
    let volume = map(this.y, height, 0, -30, -6);
    console.log(volume);
    this.synth.volume.value = volume;
    this.synth.triggerAttackRelease(this.x, 1);
  }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.rawgit.com/kylestetz/AudioKeys/master/dist/audiokeys.js