/* * Snowing routine based on one element dynamically * injected in the background of the page. * * The code is not optimized, feel free to make your own edits! * * Copyright 2010 by David Flanagan * http://creativecommons.org/licenses/by-nc-sa/3.0/ * * Modified by Giorgio Sardo * http://blogs.msdn.com/Giorgio */ (function () { // Start Animation only if browser support if (document.createElement('canvas').getContext) { if (document.readyState === 'complete') Snow(); else window.addEventListener('DOMContentLoaded', Snow, false); } else { return; } var deg = Math.PI / 180; // For converting degrees to radians var sqrt3_2 = Math.sqrt(3) / 2; // Height of an equilateral triangle var flakes = []; // Things that are dropping var scrollspeed = 64; // How often we animate things var snowspeed = 200; // How often we add a new snowflake var maxflakes = 20; // Max number of flakes to be added at the same time var rand = function (n) { return Math.floor(n * Math.random()); } var canvas, sky; var snowingTimer; var invalidateMeasure = false; function Snow() { canvas = document.createElement('canvas'); canvas.style.position = 'fixed'; canvas.style.top = '0px'; canvas.style.left = '0px'; canvas.style.zIndex = '-1'; document.body.insertBefore(canvas, document.body.firstChild); sky = canvas.getContext('2d'); ResetCanvas(); snowingTimer = setInterval(createSnowflake, snowspeed); setInterval(moveSnowflakes, scrollspeed); window.addEventListener('resize', ResetCanvas, false); } function ResetCanvas() { invalidateMeasure = true; canvas.width = document.body.offsetWidth; canvas.height = window.innerHeight; sky.strokeStyle = '#0066CC'; sky.fillStyle = 'white'; } function drawFlake(x, y, size, order) { sky.save(); sky.translate(x, y); snowflake(order, 0, Math.floor(sqrt3_2 * y), size); sky.fill(); sky.stroke(); sky.restore(); } function snowflake(n, x, y, len) { sky.save(); // Save current transformation sky.beginPath(); sky.translate(x, y); // Translate to starting point sky.moveTo(0, 0); // Begin a new subpath there leg(n); // Draw the first leg of the fractal sky.rotate(-120 * deg); // Rotate 120 degrees anticlockwise leg(n); // Draw the second leg sky.rotate(-120 * deg); // Rotate again. leg(n); // Draw the final leg sky.closePath(); // Close the subpath sky.restore(); // Restore original transformation // Draw a single leg of a level-n Koch snowflake. // This function leaves the current point at the end of // the leg it has drawn and translates the coordinate // system so the current point is (0,0). This means you // can easily call rotate() after drawing a leg. function leg(n) { sky.save(); // Save current transform if (n == 0) { // Non-recursive case: sky.lineTo(len, 0); // Just a horizontal line } else { // Recursive case: _ _ // draw 4 sub-legs like: \/ sky.scale(1 / 3, 1 / 3); // Sub-legs are 1/3rd size leg(n - 1); // Draw the first sub-leg sky.rotate(60 * deg); // Turn 60 degrees clockwise leg(n - 1); // Draw the second sub-leg sky.rotate(-120 * deg); // Rotate 120 degrees back leg(n - 1); // Third sub-leg sky.rotate(60 * deg); // Back to original heading leg(n - 1); // Final sub-leg } sky.restore(); // Restore the transform sky.translate(len, 0); // Translate to end of leg } } function createSnowflake() { var order = 2; var size = 10 + rand(90); // var t = (document.body.offsetWidth - 964) / 2; // var x = (rand(2) == 0) ? rand(t) : t + 964 + rand(t); // Make it fit with my blog var x = rand(document.body.offsetWidth); var y = window.pageYOffset; flakes.push({ x: x, y: y, vx: 0, vy: 3 + rand(3), size: size, order: order }); if (flakes.length > maxflakes) clearInterval(snowingTimer); } function moveSnowflakes() { sky.clearRect(0, 0, canvas.width, canvas.height); var maxy = canvas.height; for (var i = 0; i < flakes.length; i++) { var flake = flakes[i]; flake.y += flake.vy; flake.x += flake.vx; if (flake.y > maxy) flake.y = 0; if (invalidateMeasure) { var t = (canvas.width - 964) / 2; flake.x = (rand(2) == 0) ? rand(t) : t + 964 + rand(t); } drawFlake(flake.x, flake.y, flake.size, flake.order); // Sometimes change the sideways velocity if (rand(4) == 1) flake.vx += (rand(11) - 5) / 10; if (flake.vx > 2) flake.vx = 2; if (flake.vx < -2) flake.vx = -2; } if (invalidateMeasure) invalidateMeasure = false; } } ());