var self = window; ;(function(self) { var canvas, context, wave1, waveInteract, mouse = { x: innerWidth * 0.5, y: innerHeight * 0.5 }, angle = 0, mouseDown = interactive = true, FPS = 60; /* * Init. */ function init() { var body = document.querySelector('body'); canvas = document.createElement('canvas'); canvas.width = innerWidth; canvas.height = innerHeight; canvas.style.position = 'absolute'; canvas.style.top = 0; canvas.style.bottom = 0; canvas.style.left = 0; canvas.style.right = 0; canvas.style.zIndex = -1; canvas.style.cursor = 'n-resize'; body.appendChild(canvas); // Browser supports canvas? if(!!(capable)) { context = canvas.getContext('2d'); // Events if('ontouchmove' in window) { canvas.addEventListener('touchstart', onTouchStart, false); canvas.addEventListener('touchend', onTouchEnd, false); canvas.addEventListener('touchmove', onTouchMove, false); } else { canvas.addEventListener('mousedown', onMouseDown, false); canvas.addEventListener('mouseup', onMouseUp, false); canvas.addEventListener('mousemove', onMouseMove, false); } window.onresize = onResize; createWaves(); } else { console.error('Please, update your browser for seeing this animation.'); } } /* * Checks if browser supports canvas element. */ function capable() { return canvas.getContext && canvas.getContext('2d'); } /* * On resize window event. */ function onResize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } /* * Mouse down event. */ function onMouseDown(event) { event.preventDefault(); mouseDown = true; } /* * Mouse up event. */ function onMouseUp(event) { event.preventDefault(); mouseDown = false; } /* * Mouse move event. */ function onMouseMove(event) { event.preventDefault(); mouse.x = event.pageX - canvas.offsetLeft; mouse.y = event.pageY - canvas.offsetTop; if(interactive) mouseDown = interactive = false; } /* * Touch start event. */ function onTouchStart(event) { event.preventDefault(); mouseDown = true; } /* * Touch end event. */ function onTouchEnd(event) { event.preventDefault(); mouseDown = false; } /* * Touch move event. */ function onTouchMove(event) { event.preventDefault(); mouse.x = event.touches[0].pageX - canvas.offsetLeft; mouse.y = event.touches[0].pageY - canvas.offsetTop; if(interactive) mouseDown = interactive = false; } /* * Create waves. */ function createWaves() { var totalPoints = 80; var center = {x: canvas.width/2, y:canvas.height/2}; var radius = 150; wave1 = new Circle(center, totalPoints, radius); waveInteract = new Circle(center, totalPoints, radius, "#2296DB"); wave(); } var Circle = function(center, _num_points, _radius, color){ this.center = center; this.points = []; this.num_points = _num_points; this.waveColor = color? color : '#f98f00'; for(var i = 0; i < _num_points; i++){ this.points.push({ radius: 200, vr: 10, spd: {y:0}, }); } this.getX = function(i){ return this.points[i].radius * Math.cos(((2*Math.PI)/this.num_points)*i) + this.center.x; }; this.getY = function(i){ return this.points[i].radius * Math.sin(((2*Math.PI)/this.num_points)*i) + this.center.y; }; }; /* * Loop logic. */ function wave() { clear(); update(); render(); requestAnimFrame(wave); } /* * Clear the whole screen. */ function clear() { context.clearRect(0, 0, innerWidth, innerHeight); }; /* * Update the waves. */ var WavePresset = function (sin_off, sin_ampl, sin_stretch, off_stretch){ this.sineOffset = sin_off; this.sineAmplitude = sin_ampl; this.sineStretch = sin_stretch; this.offsetStretch = off_stretch; } WavePresset.prototype.SineF = function(x, offset){ result = this.sineOffset + this.sineAmplitude * Math.sin( x * this.sineStretch + offset * this.offsetStretch); return result; } // Create some sine wave pressets var w1 = new WavePresset(-2.037,4.881,0.012,0.044); var w2 = new WavePresset(-2.665,2.185,0.018,0.041); var w3 = new WavePresset(1.066,8.527,0.03,0.049); var w4 = new WavePresset(-1.173,2.52,0.002,0.09); var w5 = new WavePresset(2.997,6.466,0.045,0.005); var w6 = new WavePresset(0.999,1.044,0.01,0.037); var w7 = new WavePresset(2.506,3.937,0.032,0.059); var wp = new WavePresset(40,10,0.1,0.39); var wp1 = new WavePresset(40,15,0.05,0.5); //var waveC = [w1,w2,w3,w4,w5,w6,w7]; var waveC = [wp,wp1,w6,w4]; var getWave = function(x, offset){ var value = 0; for (var i=0; i < waveC.length; i++){ value += waveC[i].SineF(x, offset); } return value; } var _h = 0; function update() { var ease, friction, threshold; friction = 0.99; //threshold = interactive ? Math.round(canvas.width / 4.5) : 280; threshold = 100; //for(var index = 0; index < (wave1.length); index++) { //var p = wave1[index]; // Update radius for (var i=0; i < wave1.num_points; i++){ var point = wave1.points[i]; var nextpoint; if(i+1 < wave1.num_points){ nextpoint = wave1.points[i+1]; }else{ nextpoint = wave1.points[0]; } var _w = getWave(_h,i); point.radius = 100 + _w; //point.radius += point.vr; // Ease //point.vr = Math.sin(i*10); //point.vr += (10 * Math.sin(i) + 250 - point.radius*2) * 0.009; //point.vr += (200 - nextpoint.radius) * 0.009; // Friction //point.vr *= friction; var distance = distanceTo(mouse, {x:wave1.getX(i), y:wave1.getY(i)}); if( distance < threshold && mouseDown){ point.vr += (distance - point.radius) * 0.003; } } updateWavePoints(waveInteract); _h += 1; // Ease //point1.vy += (point1.depth - point1.y) * (interactive ? 0.03 : 0.009); // Friction //point1.vy *= friction; // Threshold for (var n = 0; n < waveInteract.num_points; n++) { var p = waveInteract.points[n]; var distance = distanceTo(mouse, {x: waveInteract.getX(n), y: waveInteract.getY(n)}); if(distance < 50 && mouseDown){ p.radius += (distance - p.radius) * 0.3; } } //if(distanceTo(mouse, point1) < threshold && mouseDown) //point1.vy += (mouse.y - point1.y) * (interactive ? 0.03 : 0.009); //} } // Number of iterations of point-influences-point to do on wave per step // (this makes the waves animate faster) var ITERATIONS = 5; // Spring constant for forces applied by adjacent points var SPRING_CONSTANT = 0.015; // Sprint constant for force applied to baseline var SPRING_CONSTANT_BASELINE = 0.005; var Y_OFFSET = 180; // Damping to apply to speed changes var DAMPING = 0.99; function updateWavePoints(wave) { var points = wave.points; for (var i = 0; i < ITERATIONS; i++) { for (var n = 0; n < wave.num_points; n++) { var p = wave.points[n]; // force to apply to this point var force = 0; // forces caused by the point immediately to the left or the right var forceFromLeft, forceFromRight; if (n == 0) { // wrap to left-to-right var dy = points[points.length - 1].radius - p.radius; forceFromLeft = SPRING_CONSTANT * dy; } else { // normally var dy = points[n - 1].radius - p.radius; forceFromLeft = SPRING_CONSTANT * dy; } if (n == points.length - 1) { // wrap to right-to-left var dy = points[0].radius- p.radius; forceFromRight = SPRING_CONSTANT * dy; } else { // normally var dy = points[n + 1].radius - p.radius; forceFromRight = SPRING_CONSTANT * dy; } // Also apply force toward the baseline var dy = Y_OFFSET - p.radius; forceToBaseline = SPRING_CONSTANT_BASELINE * dy; // Sum up forces force = force + forceFromLeft; force = force + forceFromRight; force = force + forceToBaseline; // Calculate acceleration var mass = 2; var acceleration = force / mass; // Apply acceleration (with damping) p.spd.y = DAMPING * p.spd.y + acceleration; // Apply speed p.radius = p.radius + p.spd.y; } } } /* * Render the waveS. */ function render() { // Smooth bezier curves clear(); var ww1 = wave1; var ww = waveInteract; var waves = [ww1,ww]; for (var i = 0; i< waves.length; i++){ context.globalCompositeOperation = 'xor'; var currentWave = waves[i]; context.save(); //context.globalAlpha = 0.5; context.fillStyle = currentWave.waveColor; context.beginPath(); context.moveTo(ww.getX(0), ww.getY(0)); // Draw N wave1 for(var N = 1; N < currentWave.num_points; N++) { context.lineTo(currentWave.getX(N), currentWave.getY(N)); }; context.lineTo(ww.getX(0), ww.getY(0)); context.fill(); context.restore(); } } /* * Distance between two wave1. */ function distanceTo(pointA, pointB) { var dx = Math.abs(pointA.x - pointB.x); var dy = Math.abs(pointA.y - pointB.y); return Math.sqrt(dx * dx + dy * dy); }; /* * Request new frame by Paul Irish. * 60 FPS. */ window.requestAnimFrame = (function() { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / FPS); }; })(); window.addEventListener ? window.addEventListener('load', init, false) : window.onload = init; })(self);