1'use strict'; 2 3// If set to true, the user must press 4// UP UP DOWN ODWN LEFT RIGHT LEFT RIGHT A B 5// to trigger the confetti with a random color theme. 6// Otherwise the confetti constantly falls. 7var onlyOnKonami = false; 8 9$(function () { 10 // Globals 11 var $window = $(window) 12 , random = Math.random 13 , cos = Math.cos 14 , sin = Math.sin 15 , PI = Math.PI 16 , PI2 = PI * 2 17 , timer = undefined 18 , frame = undefined 19 , confetti = []; 20 21 // Settings 22 var konami = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65] 23 , pointer = 0; 24 25 var particles = 150 26 , spread = 250 27 , sizeMin = 3 28 , sizeMax = 12 - sizeMin 29 , eccentricity = 10 30 , deviation = 100 31 , dxThetaMin = -.1 32 , dxThetaMax = -dxThetaMin - dxThetaMin 33 , dyMin = .13 34 , dyMax = .18 35 , dThetaMin = .4 36 , dThetaMax = .7 - dThetaMin; 37 38 var colorThemes = [ 39 function () { 40 return 'rgb(255, 236, 139)'; // ãã¹ã¦ã®ç´å¹éªãè¨å® 41 } 42 ]; 43 44 function color(r, g, b) { 45 return 'rgb(' + r + ',' + g + ',' + b + ')'; 46 } 47 48 // Cosine interpolation 49 function interpolation(a, b, t) { 50 return (1 - cos(PI * t)) / 2 * (b - a) + a; 51 } 52 53 // Create a 1D Maximal Poisson Disc over [0, 1] 54 var radius = 1 / eccentricity, radius2 = radius + radius; 55 function createPoisson() { 56 // domain is the set of points which are still available to pick from 57 // D = union{ [d_i, d_i+1] | i is even } 58 var domain = [radius, 1 - radius], measure = 1 - radius2, spline = [0, 1]; 59 while (measure) { 60 var dart = measure * random(), i, l, interval, a, b, c, d; 61 62 // Find where dart lies 63 for (i = 0, l = domain.length, measure = 0; i < l; i += 2) { 64 a = domain[i], b = domain[i + 1], interval = b - a; 65 if (dart < measure + interval) { 66 spline.push(dart += a - measure); 67 break; 68 } 69 measure += interval; 70 } 71 c = dart - radius, d = dart + radius; 72 73 // Update the domain 74 for (i = domain.length - 1; i > 0; i -= 2) { 75 l = i - 1, a = domain[l], b = domain[i]; 76 // c---d c---d Do nothing 77 // c-----d c-----d Move interior 78 // c--------------d Delete interval 79 // c--d Split interval 80 // a------b 81 if (a >= c && a < d) 82 if (b > d) domain[l] = d; // Move interior (Left case) 83 else domain.splice(l, 2); // Delete interval 84 else if (a < c && b > c) 85 if (b <= d) domain[i] = c; // Move interior (Right case) 86 else domain.splice(i, 0, c, d); // Split interval 87 } 88 89 // Re-measure the domain 90 for (i = 0, l = domain.length, measure = 0; i < l; i += 2) 91 measure += domain[i + 1] - domain[i]; 92 } 93 94 return spline.sort(); 95 } 96 97 // Create the overarching container 98 var container = document.createElement('div'); 99 container.style.position = 'fixed'; 100 container.style.top = '0'; 101 container.style.left = '0'; 102 container.style.width = '100%'; 103 container.style.height = '0'; 104 container.style.overflow = 'visible'; 105 container.style.zIndex = '9999'; 106 107 // Confetto constructor 108 function Confetto(theme) { 109 this.frame = 0; 110 this.outer = document.createElement('div'); 111 this.inner = document.createElement('div'); 112 this.outer.appendChild(this.inner); 113 114 var outerStyle = this.outer.style, innerStyle = this.inner.style; 115 outerStyle.position = 'absolute'; 116 outerStyle.width = (sizeMin + sizeMax * random()) + 'px'; 117 outerStyle.height = (sizeMin + sizeMax * random()) + 'px'; 118 innerStyle.width = '100%'; 119 innerStyle.height = '100%'; 120 innerStyle.backgroundColor = theme(); 121 122 outerStyle.perspective = '50px'; 123 outerStyle.transform = 'rotate(' + (360 * random()) + 'deg)';
124 this.axis = 'rotate3D(' + 125 cos(360 * random()) + ',' + 126 cos(360 * random()) + ',0,'; 127 this.theta = 360 * random(); 128 this.dTheta = dThetaMin + dThetaMax * random(); 129 innerStyle.transform = this.axis + this.theta + 'deg)'; 130 131 this.x = $window.width() * random(); 132 this.y = -deviation; 133 this.dx = sin(dxThetaMin + dxThetaMax * random()); 134 this.dy = dyMin + dyMax * random(); 135 outerStyle.left = this.x + 'px'; 136 outerStyle.top = this.y + 'px'; 137 138 // Create the periodic spline 139 this.splineX = createPoisson(); 140 this.splineY = []; 141 for (var i = 1, l = this.splineX.length - 1; i < l; ++i) 142 this.splineY[i] = deviation * random(); 143 this.splineY[0] = this.splineY[l] = deviation * random(); 144 145 this.update = function (height, delta) { 146 this.frame += delta; 147 this.x += this.dx * delta; 148 this.y += this.dy * delta; 149 this.theta += this.dTheta * delta; 150 151 // Compute spline and convert to polar 152 var phi = this.frame % 7777 / 7777, i = 0, j = 1; 153 while (phi >= this.splineX[j]) i = j++; 154 var rho = interpolation( 155 this.splineY[i], 156 this.splineY[j], 157 (phi - this.splineX[i]) / (this.splineX[j] - this.splineX[i]) 158 ); 159 phi *= PI2; 160 161 outerStyle.left = this.x + rho * cos(phi) + 'px'; 162 outerStyle.top = this.y + rho * sin(phi) + 'px'; 163 innerStyle.transform = this.axis + this.theta + 'deg)'; 164 return this.y > height + deviation; 165 }; 166 } 167 168 function poof() { 169 if (!frame) { 170 // Append the container 171 document.body.appendChild(container); 172 173 // Add confetti 174 var theme = colorThemes[onlyOnKonami ? colorThemes.length * random() | 0 : 0] 175 , count = 0; 176 (function addConfetto() { 177 if (onlyOnKonami && ++count > particles) 178 return timer = undefined; 179 180 var confetto = new Confetto(theme); 181 confetti.push(confetto); 182 container.appendChild(confetto.outer); 183 timer = setTimeout(addConfetto, spread * random()); 184 })(0); 185 186 // Start the loop 187 var prev = undefined; 188 requestAnimationFrame(function loop(timestamp) { 189 var delta = prev ? timestamp - prev : 0; 190 prev = timestamp; 191 var height = $window.height(); 192 193 for (var i = confetti.length - 1; i >= 0; --i) { 194 if (confetti[i].update(height, delta)) { 195 container.removeChild(confetti[i].outer); 196 confetti.splice(i, 1); 197 } 198 } 199 200 if (timer || confetti.length) 201 return frame = requestAnimationFrame(loop); 202 203 // Cleanup 204 document.body.removeChild(container); 205 frame = undefined; 206 }); 207 } 208 } 209 210 $window.keydown(function (event) { 211 pointer = konami[pointer] === event.which 212 ? pointer + 1 213 : +(event.which === konami[0]); 214 if (pointer === konami.length) { 215 pointer = 0; 216 poof(); 217 } 218 }); 219 220 if (!onlyOnKonami) poof(); 221});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.