<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();