<div id="canvas-holder"></div>
// Interaction vars. Play about with these numbers :)




var NUM_CIRCLES = 300;
var MAX_RADIUS = 800;
var FRICTION = 1;
var SPEED_DIVISOR = 1000;
var WEIGHT_1 = 5;
var WEIGHT_2 = 3.5;
var SPREAD = 1;

// Vars -
var _loader;
var _imgTexture;
var _stage;
var _target;
var _renderer;
var _mouseDown = false;
var _circles = [];
// Stage width & height - 
var _sw;
var _sh;

// Start Mouse X & Y at not 0 for some initial movement - 
var _mouseX = 3;
var _mouseY = 3;

const context = new (window.AudioContext || window.webkitAudioContext)();
//var context = new AudioContext();
var osc = context.createOscillator();
var vol = context.createGain();
var osc2 = context.createOscillator();
var vol2 = context.createGain();
var real = new Float32Array(2);
var imag = new Float32Array(2);
real[0] = 0.0;
imag[0] = 0.0;
real[1] = 0.0;
imag[1] = 0;
var push = false;
var wave = context.createPeriodicWave(real, imag, {disableNormalization: true});
const lfo = context.createOscillator();  
const modulationGain = context.createGain();  
function soundSetup(){
vol.gain.value = 0.00; // from 0 to 1, 1 full volume, 0 is muted
osc.connect(vol); // connect osc to vol
vol.connect(context.destination); // connect vol to context destination
//osc.start(context.currentTime); // start it three seconds from now
vol2.gain.value = 0.0; // from 0 to 1, 1 full volume, 0 is muted
osc2.connect(vol2); // connect osc to vol
vol2.connect(context.destination); // connect vol to context destination
//osc2.start(context.currentTime); // start it three seconds from now
osc.setPeriodicWave(wave);

  lfo.frequency.value = 0.0;
  
  modulationGain.gain.value = 0;  // Configure the graph and start the oscillators  
  lfo.connect(modulationGain);  
  modulationGain.connect(osc2.frequency);
  modulationGain.connect(osc.detune);
}
function init() {


    soundSetup();
    // Call the resize function to set up defaults -
    resizeIt();
    // On resize, recall the resize function -
    window.onresize = resizeIt;

    // Set up out Pixi instance -
    _stage = new PIXI.Stage();
    _renderer = PIXI.autoDetectRenderer(_sw, _sh);
    _renderer.backgroundColor = 0xffffff; 
    _renderer.view.style.display = "block";

    // Add some Mouse & Touch events -
    _stage.on('mousedown', onMouseDown);
    _stage.on('touchstart', onMouseDown);
    _stage.on('mousemove', onMouseMove);
    _stage.on('touchmove', onMouseMove);
    _stage.on('mouseup', onMouseUp);
    _stage.on('touchend', onMouseUp);

    // Tell the stage that it should be interactive -
    _stage.interactive = true;
    _stage.hitArea = new PIXI.Rectangle(0, 0, _sw, _sh);

    // Add render view to DOM
    document.getElementById("canvas-holder").appendChild(_renderer.view);

    // Make our main container, and add it to the stage -
    _target = new PIXI.Container();
    _target.position.x = _sw / 2 ;
    _target.position.y = _sh / 2 -500 ;
    _stage.addChild(_target);

    // Make a loader to "load" the image -
    _loader = new PIXI.loaders.Loader();
    _loader.add("img", _myImage);
    _loader.once('complete', addCircles);

    // Begin loading -
    _loader.load();
}

function addCircles() {

    // Create a texture from the image -
    _imgTexture = PIXI.utils.TextureCache[_myImage];

    // Make the circles -
    for (var i = 0; i < NUM_CIRCLES; i++) {

        // Set the radius to be between the max and 0 - based on the current index of the loop.
        var radius = map(i, 0, NUM_CIRCLES - 1, MAX_RADIUS, 0);

        // Create a container -
        var circleHolder = new PIXI.Container();

        // Create a sprite from the texture -
        var circleSprite = new PIXI.Sprite(_imgTexture);

        // Center the sprite -
        circleSprite.anchor.x = 0.5
        circleSprite.anchor.y = 0.5;

        // Add it to the holder -
        circleHolder.addChild(circleSprite);

        // Create a circular graphic to use as a mask -
        var circleMask = new PIXI.Graphics();
        circleMask.beginFill(0xFFFFFF);
        circleMask.drawCircle(0, 0, radius);
        circleMask.endFill();

        // Add it to the container -
        circleHolder.addChild(circleMask);

        // Set it as the mask of the sprite -
        circleSprite.mask = circleMask;

        // Set some properties, to be used later for the animation -
      
      circleHolder.speedX = 0;
        circleHolder.speedY = 0;
        circleHolder.distX = 0;
        circleHolder.distY = 0;

        // Add a weight, mapped between the 2 variables, again, based on the loop index
        circleHolder.weight = map(i, 0, NUM_CIRCLES - 1, WEIGHT_1, WEIGHT_2);

        // Cache the whole clip as a bitmap
        circleHolder.cacheAsBitmap = true;

        // Add it to an array of the circles -
        _circles.push(circleHolder);

        // Add the clip to the target container -
        _target.addChild(circleHolder);
    }

    // Initial call of the animate funciton -
    setrand() ;
    animate();
}

function resizeIt() {

    // Calculate our size vars -
    _sw = window.innerWidth;
    _sh = window.innerHeight;

    // Resize the renderer -
    if (_renderer) {
        _renderer.resize(_sw, _sh);
        _stage.hitArea = new PIXI.Rectangle(0, 0, _sw, _sh);
    }
    // Recenter our container -
    if (_target) {
        _target.position.x = _sw / 2;
        _target.position.y = _sh / 2;
    }

}
var fr = 0.00; 
function animate() {

    var circ;

    // For each circle -
    for (var i = _circles.length - 1; i >= 0; i--) {

        circ = _circles[i];
        
      
        
        // Calculate the distance to the mouse -
        circ.distX = Math.floor(circ.position.x - _mouseX);
        circ.distY = Math.floor(circ.position.y - _mouseY);
        
        // Divide the distance to make the transition not instant, and add that to its speed
        circ.speedX += circ.distX / SPEED_DIVISOR;
        circ.speedY += circ.distY / SPEED_DIVISOR;

        // Reposition the circle based on its speed & weight variables -
        circ.position.x -= circ.speedX * circ.weight;
        circ.position.y -= circ.speedY * circ.weight;
        //if (circ.position.x > _sw || circ.position.x < 0) circ.speedX = -circ.speedX;
        //if (circ.position.y > _sh || circ.position.y < 0) circ.speedY = -circ.speedY;
        // Apply friction to the circle's speed -
        if(push){
        circ.speedX+=random(SPREAD);
        circ.speedY+=random(SPREAD);
          
    }
        circ.speedX *= FRICTION;
        circ.speedY *= FRICTION;
    }
    push = false;
    fr = map(_circles[_circles.length - 1].distX,0,1000,50,500);
    osc.frequency.setValueAtTime(fr, context.currentTime);
    fr = map(_circles[0].distX,0,1000,50,200);
    osc2.frequency.setValueAtTime(fr, context.currentTime);
    // Render the stage -
    _renderer.render(_stage);
 
    // Call animate again -
    requestAnimationFrame(animate);
}
var timer;
function onMouseDown(mouseData) {
    
    // Set the mouse down flag -
    _mouseDown = true;
    timer = context.currentTime;
    console.log(timer);
    // Set the mouse position vars -
    var mouse = mouseData.data.getLocalPosition(_stage);
    _mouseX = mouse.x/2 - _sw / 4;
    _mouseY = mouse.y/2 - MAX_RADIUS/2 + 90 ;
}
var click  = false;
function onMouseMove(mouseData) {
    if (_mouseDown) {
        // Set the mouse position vars -
        var mouse = mouseData.data.getLocalPosition(_stage);
        _mouseX = mouse.x/2 - _sw / 4;
        _mouseY = mouse.y/2 - _sh / 4;
    }
}
var firstTime = true;
function onMouseUp() {
  
	if(firstTime){
	osc.start(context.currentTime);
	osc2.start(context.currentTime);
	firstTime = false;
	}
    if(context.currentTime - timer < 0.1 && !click) click = true;
    else if(context.currentTime - timer < 0.15 && click) {
      reset();
      click = false;
    }
    else {
      click = false;
          push = true;
         }
    _mouseDown = false;

}
function reset() {
      _mouseX = 0;
      _mouseY = 0;
      for (var i = _circles.length - 1; i >= 0; i--) {

        circ = _circles[i];
               
        // Calculate the distance to the mouse -
        circ.distX = random(0);
        circ.distY = random(0);

        // Divide the distance to make the transition not instant, and add that to its speed
        circ.speedX = 0.5;
        circ.speedY = 0.2;

        // Reposition the circle based on its speed & weight variables -
        circ.position.x = random(0);
        circ.position.y = random(0);
    }
}

function setrand() {
     
}

function random(max) {
  return Math.floor(Math.random() * max);
}
// Maths utility to map numbers from one range to another -
function map(v, a, b, x, y) {
    return (v == a) ? x : (v - a) * (y - x) / (b - a) + x;
}

const imgs = [ 
"https://static.tildacdn.com/tild3934-3165-4939-a330-393131376333/121043020027.jpg",
];

const rand = Math.floor(Math.random() * imgs.length);
var _myImage = imgs[rand];
// Start -
init();