var snowStorm = null; function SnowStorm() { this.flakesMax = 128; this.flakesMaxActive = 64; this.animationInterval = 33; this.flakeBottom = null; this.targetElement = null; this.followMouse = true; this.snowColor = 'white'; this.snowCharacter = '•'; this.snowStick = true; this.useMeltEffect = true; this.useTwinkleEffect = false; this.usePositionFixed = false; this.flakeLeftOffset = 0; this.flakeRightOffset = 0; this.flakeWidth = 10; this.flakeHeight = 10; this.vMaxX = 5; this.vMaxY = 4; this.zIndex = 0; var addEvent = (typeof(window.attachEvent)=='undefined'?function(o,evtName,evtHandler) { return o.addEventListener(evtName,evtHandler,false); }:function(o,evtName,evtHandler) { return o.attachEvent('on'+evtName,evtHandler); });
var removeEvent = (typeof(window.attachEvent)=='undefined'?function(o,evtName,evtHandler) { return o.removeEventListener(evtName,evtHandler,false); }:function(o,evtName,evtHandler) { return o.detachEvent('on'+evtName,evtHandler); });
function rnd(n,min) { if (isNaN(min)) { min = 0; } return (Math.random()*n)+min; }
function plusMinus(n) { return (parseInt(rnd(2),10)==1?n*-1:n); }
var s = this; var storm = this; this.timers = []; this.flakes = []; this.disabled = false; this.active = false;
var isIE = navigator.userAgent.match(/msie/i); var isIE6 = navigator.userAgent.match(/msie 6/i); var isOldIE = (isIE && (isIE6 || navigator.userAgent.match(/msie 5/i))); var isWin9X = navigator.appVersion.match(/windows 98/i); var isiPhone = navigator.userAgent.match(/iphone/i); var isBackCompatIE = (isIE && document.compatMode == 'BackCompat'); var noFixed = ((isBackCompatIE || isIE6 || isiPhone)?true:false); var screenX = null; var screenX2 = null; var screenY = null; var scrollY = null; var vRndX = null; var vRndY = null; var windOffset = 1; var windMultiplier = 2; var flakeTypes = 6; var fixedForEverything = false; var opacitySupported = (function(){ try { document.createElement('div').style.opacity = '0.5'; } catch (e) { return false; } return true; })(); var docFrag = document.createDocumentFragment(); if (s.flakeLeftOffset === null) { s.flakeLeftOffset = 0; } if (s.flakeRightOffset === null) { s.flakeRightOffset = 0; }
this.meltFrameCount = 20;
this.meltFrames = [];
for (var i=0; i
this.animate = function() { // main animation loop // move, check status, die etc. s.move(); };
this.setVelocities = function() { s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1); s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1); };
this.setOpacity = function(o,opacity) { if (!opacitySupported) { return false; } o.style.opacity = opacity; };
this.melt = function() {
if (!storm.useMeltEffect || !s.melting) {
s.recycle();
} else {
if (s.meltFrame < s.meltFrameCount) {
s.meltFrame++;
s.setOpacity(s.o,s.meltFrames[s.meltFrame]);
s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px';
s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px';
} else {
s.recycle();
}
}
};
this.recycle = function() {
s.o.style.display = 'none';
s.o.style.position = (fixedForEverything?'fixed':'absolute');
s.o.style.bottom = 'auto';
s.setVelocities();
s.vCheck();
s.meltFrame = 0;
s.melting = false;
s.setOpacity(s.o,1);
s.o.style.padding = '0px';
s.o.style.margin = '0px';
s.o.style.fontSize = s.fontSize+'px';
s.o.style.lineHeight = (storm.flakeHeight+2)+'px';
s.o.style.textAlign = 'center';
s.o.style.verticalAlign = 'baseline';
s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10);
s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight;
s.refresh();
s.o.style.display = 'block';
s.active = 1;
};
this.recycle(); // set up x/y coords etc.
this.refresh();
};
this.snow = function() {
var active = 0;
var used = 0;
var waiting = 0;
var flake = null;
for (var i=s.flakes.length; i--;) {
if (s.flakes[i].active == 1) {
s.flakes[i].move();
active++;
} else if (s.flakes[i].active === 0) {
used++;
} else {
waiting++;
}
if (s.flakes[i].melting) {
s.flakes[i].melt();
}
}
if (active
this.timerInit = function() { s.timers = (!isWin9X?[setInterval(s.snow,s.animationInterval)]:[setInterval(s.snow,s.animationInterval*3),setInterval(s.snow,s.animationInterval)]); };
this.init = function() { s.randomizeWind(); s.createSnow(s.flakesMax); // create initial batch addEvent(window,'resize',s.resizeHandler); addEvent(window,'scroll',s.scrollHandler); if (!isOldIE) { addEvent(window,'blur',s.freeze); addEvent(window,'focus',s.resume); } s.resizeHandler(); s.scrollHandler(); if (s.followMouse) { addEvent(document,'mousemove',s.mouseMove); } s.animationInterval = Math.max(20,s.animationInterval); s.timerInit(); };
var didInit = false;
this.start = function(bFromOnLoad) { if (!didInit) { didInit = true; } else if (bFromOnLoad) { // already loaded and running return true; } if (typeof s.targetElement == 'string') { var targetID = s.targetElement; s.targetElement = document.getElementById(targetID); if (!s.targetElement) { throw new Error('Snowstorm: Unable to get targetElement "'+targetID+'"'); } } if (!s.targetElement) { s.targetElement = (!isIE?(document.documentElement?document.documentElement:document.body):document.body); } if (s.targetElement != document.documentElement && s.targetElement != document.body) { s.resizeHandler = s.resizeHandlerAlt; // re-map handler to get element instead of screen dimensions } s.resizeHandler(); // get bounding box elements s.usePositionFixed = (s.usePositionFixed && !noFixed); // whether or not position:fixed is supported fixedForEverything = s.usePositionFixed; if (screenX && screenY && !s.disabled) { s.init(); s.active = true; } };
function doStart() { s.start(true); }
if (document.addEventListener) { // safari 3.0.4 doesn't do DOMContentLoaded, maybe others - use a fallback to be safe. document.addEventListener('DOMContentLoaded',doStart,false); window.addEventListener('load',doStart,false); } else { addEvent(window,'load',doStart); }
} snowStorm = new SnowStorm();
function IE(e) { if (navigator.appName == "Microsoft Internet Explorer" && (event.button == "2" || event.button == "3")) { return false; } } function NS(e) { if (document.layers || (document.getElementById && !document.all)) { if (e.which == "2" || e.which == "3") { return false; } } } document.onmousedown=IE;document.onmouseup=NS;document.oncontextmenu=new Function("return false");
(function() { var canvas, ctx, circ, nodes, mouse, SENSITIVITY, SIBLINGS_LIMIT, DENSITY, NODES_QTY, ANCHOR_LENGTH, MOUSE_RADIUS;
SENSITIVITY = 100;
SIBLINGS_LIMIT = 10;
DENSITY = 50;
NODES_QTY = 0;
ANCHOR_LENGTH = 20;
MOUSE_RADIUS = 200;
circ = 2 * Math.PI; nodes = [];
canvas = document.querySelector('canvas'); resizeWindow(); mouse = { x: canvas.width / 2, y: canvas.height / 2 }; ctx = canvas.getContext('2d'); if (!ctx) { alert("Ooops! Your browser does not support canvas :'("); }
function Node(x, y) { this.anchorX = x; this.anchorY = y; this.x = Math.random() * (x - (x - ANCHOR_LENGTH)) + (x - ANCHOR_LENGTH); this.y = Math.random() * (y - (y - ANCHOR_LENGTH)) + (y - ANCHOR_LENGTH); this.vx = Math.random() * 2 - 1; this.vy = Math.random() * 2 - 1; this.energy = Math.random() * 100; this.radius = Math.random(); this.siblings = []; this.brightness = 0; }
Node.prototype.drawNode = function() { var color = "rgba(255, 0, 0, " + this.brightness + ")"; ctx.beginPath(); ctx.arc(this.x, this.y, 2 * this.radius + 2 * this.siblings.length / SIBLINGS_LIMIT, 0, circ); ctx.fillStyle = color; ctx.fill(); };
Node.prototype.drawConnections = function() { for (var i = 0; i < this.siblings.length; i++) { var color = "rgba(255, 0, 0, " + this.brightness + ")"; ctx.beginPath(); ctx.moveTo(this.x, this.y); ctx.lineTo(this.siblings[i].x, this.siblings[i].y); ctx.lineWidth = 1 - calcDistance(this, this.siblings[i]) / SENSITIVITY; ctx.strokeStyle = color; ctx.stroke(); } }; Node.prototype.moveNode = function() { this.energy -= 2; if (this.energy < 1) { this.energy = Math.random() * 100; if (this.x - this.anchorX < -ANCHOR_LENGTH) { this.vx = Math.random() * 2; } else if (this.x - this.anchorX > ANCHOR_LENGTH) { this.vx = Math.random() * -2; } else { this.vx = Math.random() * 4 - 2; } if (this.y - this.anchorY < -ANCHOR_LENGTH) { this.vy = Math.random() * 2; } else if (this.y - this.anchorY > ANCHOR_LENGTH) { this.vy = Math.random() * -2; } else { this.vy = Math.random() * 4 - 2; } } this.x += this.vx * this.energy / 100; this.y += this.vy * this.energy / 100; };
function initNodes() { ctx.clearRect(0, 0, canvas.width, canvas.height); nodes = []; for (var i = DENSITY; i < canvas.width; i += DENSITY) { for (var j = DENSITY; j < canvas.height; j += DENSITY) { nodes.push(new Node(i, j)); NODES_QTY++; } } } function calcDistance(node1, node2) { return Math.sqrt(Math.pow(node1.x - node2.x, 2) + (Math.pow(node1.y - node2.y, 2))); } function findSiblings() { var node1, node2, distance; for (var i = 0; i < NODES_QTY; i++) { node1 = nodes[i]; node1.siblings = []; for (var j = 0; j < NODES_QTY; j++) { node2 = nodes[j]; if (node1 !== node2) { distance = calcDistance(node1, node2); if (distance < SENSITIVITY) { if (node1.siblings.length < SIBLINGS_LIMIT) { node1.siblings.push(node2); } else { var node_sibling_distance = 0; var max_distance = 0; var s; for (var k = 0; k < SIBLINGS_LIMIT; k++) { node_sibling_distance = calcDistance(node1, node1.siblings[k]); if (node_sibling_distance > max_distance) { max_distance = node_sibling_distance; s = k; } } if (distance < max_distance) { node1.siblings.splice(s, 1); node1.siblings.push(node2); } } } } } } } function redrawScene() { resizeWindow(); ctx.clearRect(0, 0, canvas.width, canvas.height); findSiblings(); var i, node, distance; for (i = 0; i < NODES_QTY; i++) { node = nodes[i]; distance = calcDistance({ x: mouse.x, y: mouse.y }, node); if (distance < MOUSE_RADIUS) { node.brightness = 1 - distance / MOUSE_RADIUS; } else { node.brightness = 0; } } for (i = 0; i < NODES_QTY; i++) { node = nodes[i]; if (node.brightness) { node.drawNode(); node.drawConnections(); } node.moveNode(); } requestAnimationFrame(redrawScene); } function initHandlers() { document.addEventListener('resize', resizeWindow, false); canvas.addEventListener('mousemove', mousemoveHandler, false); } function resizeWindow() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } function mousemoveHandler(e) { mouse.x = e.clientX; mouse.y = e.clientY; } initHandlers(); initNodes(); redrawScene(); })();