// NOTE: This script does not work in some browsers, due to lack of support for SVG effects/animation.
'use strict';
function letItSnow(options) { // <3 CC0
var SVG_NS = 'http://www.w3.org/2000/svg';
var getSnowflakeArm = function (x, y, radius) {
// TODO: this could be enhanced to make much more intersting snowflake shapes, with input parameters and/or randomized values
// round all numbers to a max of 2 decimal places
var x0 = Math.round(x * 100) / 100;
var y0 = Math.round(y * 100) / 100;
radius = Math.round(radius * 100) / 100;
var radiusOffset1 = radius / 5;
var xArm1 = radius / 5;
var yArm1 = radius / 10;
var radiusOffset2 = radiusOffset1 * 2;
var xArm2 = xArm1 * 2;
var yArm2 = yArm1 * 2;
var armPoints = [];
// draw from center to tip
armPoints.push({ a: 'M', x: x0, y: y0 });
armPoints.push({ a: 'L', x: x0, y: y0 - radius });
// draw first spoke -- from tip, to center, to tip
armPoints.push({ a: 'M', x: x0 + xArm1, y: y0 - radius + yArm1 });
armPoints.push({ a: 'L', x: x0, y: y0 - radius + radiusOffset1 });
armPoints.push({ a: 'L', x: x0 - xArm1, y: y0 - radius + yArm1 });
// draw second spoke
armPoints.push({ a: 'M', x: x0 + xArm2, y: y0 - radius + yArm2 });
armPoints.push({ a: 'L', x: x0, y: y0 - radius + radiusOffset2 });
armPoints.push({ a: 'L', x: x0 - xArm2, y: y0 - radius + yArm2 });
var d = '';
for (var j = 0; j < armPoints.length; j++) {
var p = armPoints[j];
d += '\n' + p.a + p.x + ',' + p.y;
}
return d;
}
var getSnowflake = function (x, y, radius, speed, spin, clockwise) {
var secondsSpin = (11 - spin) / 4; // spin should be from 1 to 10
var sign = clockwise ? 1 : -1;
var g = document.createElementNS(SVG_NS, 'g');
// the bigger the snowflake, the thicker you need the lines to be
var strokeWidth = Math.round(radius / 15 * 100) / 100;
var d = getSnowflakeArm(x, 0, radius);
for (var i = 0; i < 6; i++) {
var path = document.createElementNS(SVG_NS, 'path');
//path.setAttribute('id','Mine' + i);
path.setAttribute('d', d);
path.setAttribute('fill', 'none');
path.setAttribute('stroke-width', strokeWidth);
path.setAttribute('stroke', '#ffffff');
var animate = document.createElementNS(SVG_NS, 'animateTransform');
animate.setAttribute('attributeName', 'transform');
animate.setAttribute('type', 'rotate');
animate.setAttribute('from', (i + 0) * 60 * sign + ' ' + x + ' ' + 0);
animate.setAttribute('to', (i + 1) * 60 * sign + ' ' + x + ' ' + 0);
animate.setAttribute('dur', secondsSpin + 's');
animate.setAttribute('repeatCount', 'indefinite');
path.appendChild(animate);
g.appendChild(path);
}
var h = window.innerHeight;
var secondsFall = h / speed;
var fallenBeginSeconds = secondsFall * y / h;
var animate = document.createElementNS(SVG_NS, 'animateTransform');
animate.setAttribute('attributeName', 'transform');
animate.setAttribute('type', 'translate');
animate.setAttribute('from', '0 ' + (0 - radius));
animate.setAttribute('to', '0 ' + (h + radius));
animate.setAttribute('dur', secondsFall + 's');
animate.setAttribute('begin', -fallenBeginSeconds + 's');
animate.setAttribute('repeatCount', 'indefinite');
g.appendChild(animate);
return g;
}
{ // validation/defaults for all used option values
if (typeof options == 'undefined') options = {};
var validOrDefault = function (value, min, max, defaultValue) {
if (isNaN(value))
return defaultValue;
value = Number(value);
if (value < min || value > max)
return defaultValue;
return value;
}
options.numFlakes = validOrDefault(options.numFlakes, 1, 500, 75);
options.minSize = validOrDefault(options.minSize, 5, 50, 5);
options.maxSize = validOrDefault(options.maxSize, 5, 50, 20);
options.minSpin = validOrDefault(options.minSpin, 0, 10, 3);
options.maxSpin = validOrDefault(options.maxSpin, 0, 10, 7);
options.minSpeed = validOrDefault(options.minSpeed, 0, 100, 10);
options.maxSpeed = validOrDefault(options.maxSpeed, 0, 100, 90);
if (isNaN(options.zIndex)) options.zIndex = -1;
}
// create <svg>, set to size of page, add animated snowflakes
var svg = document.createElementNS(SVG_NS, 'svg');
svg.setAttribute('width', window.innerWidth);
svg.setAttribute('height', window.innerHeight);
svg.style.position = 'fixed';
svg.style.left = 0;
svg.style.top = 0;
svg.style.zIndex = options.zIndex;
for (var i = 0; i < options.numFlakes; i++) {
var x = Math.random() * window.innerWidth;
var y = Math.random() * window.innerHeight;
var radius = Math.random() * (options.maxSize - options.minSize) + options.minSize;
var spin = Math.random() * (options.maxSpin - options.minSpin) + options.minSpin;
var clockwise = (Math.random() > 0.5);
var speed = Math.random() * (options.maxSpeed - options.minSpeed) + options.minSpeed;
var snowflake = getSnowflake(x, y, radius, speed, spin, clockwise);
svg.appendChild(snowflake);
}
if (isNaN(options.delay) == false) {
var delaySeconds = Number(options.delay);
if (delaySeconds > 0) {
svg.style.display = 'none';
window.setTimeout(function () { svg.style.display = ''; },
delaySeconds * 1000);
}
}
document.body.appendChild(svg);
}
No comments:
Post a Comment