An alternative to UBB.threads
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
FLocal/static/js/machichara/fractalsnow-specific.js

145 lines
6.2 KiB

/*
* The snowflake() function below is the cool part of this hack.
* It draws a fractal, but includes only a single line-drawing command.
* A 4th order Koch snowflake consists of 768 connected line segments,
* and this function draws them all with c.lineTo(0,len). The secret
* is the way it manipulates the transformation matrix before drawing
* each line. Probably not the most efficient way to write the code
* but a fun exercise in <canvas> transformations.
*
* The code to make the snowflakes fall is pretty standard CSS animation.
* Not the cleanest code I've written, but I need to get back to finishing
* the 6th edition of JavaScript: The Definitive Guide.
*
* This ought to work in IE9 beta, since that browser supports <canvas>.
* But it doesn't seem to. I took the shortcut of using window.innerHeight
* and window.pageYOffset, and I'm guess that is what is breaking it.
*
* Copyright 2010 by David Flanagan
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*/
(function() {
// If we don't have a working <canvas> element, apologize and quit
if (!document.createElement("canvas").getContext) {
return;
}
// Draw a level-n Koch Snowflake fractal in the context c,
// with lower-left corner at (x,y) and side length len.
function snowflake(c, n, x, y, len) {
c.save(); // Save current transformation
c.translate(x,y); // Translate to starting point
c.moveTo(0,0); // Begin a new subpath there
leg(n); // Draw the first leg of the fractal
c.rotate(-120*deg); // Rotate 120 degrees anticlockwise
leg(n); // Draw the second leg
c.rotate(-120*deg); // Rotate again.
leg(n); // Draw the final leg
c.closePath(); // Close the subpath
c.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) {
c.save(); // Save current transform
if (n == 0) { // Non-recursive case:
c.lineTo(len, 0); // Just a horizontal line
}
else { // Recursive case: _ _
// draw 4 sub-legs like: \/
c.scale(1/3,1/3); // Sub-legs are 1/3rd size
leg(n-1); // Draw the first sub-leg
c.rotate(60*deg); // Turn 60 degrees clockwise
leg(n-1); // Draw the second sub-leg
c.rotate(-120*deg); // Rotate 120 degrees back
leg(n-1); // Third sub-leg
c.rotate(60*deg); // Back to original heading
leg(n-1); // Final sub-leg
}
c.restore(); // Restore the transform
c.translate(len, 0); // Translate to end of leg
}
}
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 = 80; // How often we animate things
var snowspeed = 1500; // How often we add a new snowflake
var rand = function(n) { return Math.floor(n*Math.random()); }
// Add a new snowflake at the top of the viewport
function createSnowflake() {
var order = 2 + rand(3); // 2nd, 3rd, or 4th order fractal
var size = 10 + rand(90);
var width = size;
var height = size*sqrt3_2*4/3;
var x = rand(window.innerWidth - size);
var y = window.pageYOffset;
// Create a <canvas> element
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
canvas.style.position = "absolute";
canvas.style.left = x + "px";
canvas.style.top = y + "px";
canvas.style.zIndex = 100 + rand(100);
// Draw a translucent snowflake into the transparent canvas
var c = canvas.getContext("2d");
c.strokeStyle = "rgba(0,0,0,0.5)";
c.fillStyle = "rgba(255,255,255,0.75)";
snowflake(c,order,0,Math.floor(sqrt3_2*size),size);
c.fill();
c.stroke();
// Add the canvas to the document and to our array of snowflakes
document.body.appendChild(canvas);
flakes.push({elt:canvas, x: x, y:y, vy:3+rand(3), width:width, height:height});
}
// This function animates the flakes falling down the screen
function moveSnowflakes() {
var maxy = window.pageYOffset + window.innerHeight;
var maxx = window.pageXOffset + window.innerWidth;
var i = 0;
while(i < flakes.length) { // Loop through the array of flakes
var flake = flakes[i];
flake.y += flake.vy;
if ((flake.y+flake.height > maxy) || (flake.x+flake.width > maxx)) {
// The flake has scrolled off, so get rid of it
document.body.removeChild(flake.elt);
flakes.splice(i, 1);
continue;
}
flake.elt.style.top = flake.y + "px"; // Move the flake down
// Move the flake side to side
if (flake.vx == undefined) flake.vx = 0;
flake.x += flake.vx;
flake.elt.style.left = flake.x + "px";
// 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;
i++;
}
}
function snow() {
// Start creating snowflakes and moving them down the screen
var scrolltimer = setInterval(moveSnowflakes, scrollspeed);
var snowtimer = setInterval(createSnowflake, snowspeed);
}
if (document.readyState === "complete") snow();
else window.addEventListener("load", snow, false);
}());