const is_iphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) const is_ipad = (navigator.userAgent.match(/iPad/i)) const is_android = (navigator.userAgent.match(/Android/i)) const is_mobile = is_iphone || is_ipad || is_android const is_desktop = !is_mobile; document.body.parentNode.classList.add(is_desktop ? 'desktop' : 'mobile') function avg(a,b,n){ return (a*(n-1) + b)/n } function rand(n){ return Math.random()*n } function randint(n) { return ~~(Math.random()*n) } function randrange(a,b){ return a+rand(b-a) } function choice(a) { return a[randint(a.length)] } function clamp(n,a,b) { return a > n ? a : n > b ? b : n } function sign(n){ return n < 0 ? -1 : 1 } function mod(n,m){ return n-(m * Math.floor(n/m)) } function lerp(n,a,b){ return (b-a)*n+a } function quantize(m,n){ return n * ((m/n)|0) } function randgauss (obj, jog) { var radius = Math.random() * jog var angle = Math.random() * Math.PI * 2 obj.left += Math.sin(angle) * radius obj.top += Math.cos(angle) * radius } function shuffle(a){ for (var i = a.length; i > 0; i--){ var r = randint(i) var swap = a[i-1] a[i-1] = a[r] a[r] = swap } return a } function toArray (els){ return Array.prototype.slice.apply(els) } // easing functions function circular (t) { return Math.sqrt( 1 - ( --t * t ) ) } function quadratic (t) { return t * ( 2 - t ) } function back (t) { var b = 4; return ( t = t - 1 ) * t * ( ( b + 1 ) * t + b ) + 1; } function bounce (t) { if (t >= 1) return 1; if ( ( t /= 1 ) < ( 1 / 2.75 ) ) { return 7.5625 * t * t; } else if ( t < ( 2 / 2.75 ) ) { return 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75; } else if ( t < ( 2.5 / 2.75 ) ) { return 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375; } else { return 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375; } } function elastic (t) { var f = 0.22, e = 0.4; if ( t === 0 ) { return 0; } if ( t == 1 ) { return 1; } return ( e * Math.pow( 2, - 10 * t ) * Math.sin( ( t - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); } function preload (url) { var img = new Image () var loaded = false, _cb img.onload = function(){ if (loaded) return loaded = true if (_cb) { _cb(img) } } img.src = url if (img.complete) { img.onload() } return { then: function(cb){ if (loaded) { cb(img) } else { _cb = cb } } } } function preloadImages () { var images = toArray(document.getElementById("images").children) var count = 0, ready = false, _cb images.forEach(function(img){ var loaded = false img.onload = function(){ if (loaded) return loaded = true done(img) } if (img.complete) { img.onload() } }) function done () { if (++count == images.length && ! ready) { ready = true _cb && _cb() } } return { then: function(cb){ if (ready) { cb() } else { _cb = cb } } } } function smoothstep(min,max,n){ var t = clamp((n - min) / (max - min), 0.0, 1.0); return t * t * (3.0 - 2.0 * t) } function detrand (x,y) { return (Math.sin( x * 12.9898 + y * 78.233 ) * 43758.5453) % 1 } function gray_to_transparency(img) { var canvas = document.createElement("canvas") var ctx = canvas.getContext('2d') var nw = img.naturalWidth, nh = img.naturalHeight canvas.width = nw canvas.height = nh ctx.drawImage(img,0,0) var pixels = ctx.getImageData(0,0,nw,nh) var data = pixels.data for (var i = 0, len = nw*nh*4; i < len; i += 4) { data[i+3] = data[i] data[i] = data[i+1] = data[i+2] = 255 } ctx.putImageData(pixels,0,0) return canvas } var TWO_PI = 2*Math.PI