MAKE IT STOP

mooSnow - javascript text snowflakes overlay class for mootools 1.2+


The holiday season is bad enough as it is - so very festive and so busy.... Decorations everywhere... It is now almost a tradition to deface your sites and put little Santa hats, ice, snow flakes and other such nuisance!

Chances are, your boss will come in soon and ask you to do something festive with your site. This is where mooSnow comes in: a simple class that creates an overlay over a target element (for example, the header of your site) and moves text-based snow flakes (ascii - *) within it NO IMAGES, NO .CSS -- all in a single configurable mootools class. Give your flash team a day off this year!

mooSnow usage


It is self explanatory, really. Look at the source and the default options, you can play with just about any setting you like - from the snowflakes' opacity, speed, size, quantity to the complete CSS styling of the flakes or the overlay element.

The default settings are pretty tweaked now in my opnion - not to be too obtrusive. You can be as annoying or as subtle to your visitors as you like - run with 5-10 snow flakes or give them a snow blizzard - your call.

Please - if you overlay on top of elements with click events, make sure the event propagation still works (not tested).

Download mooSnow


http://fragged.org/js/moo_snow.js (don't hotlink, I am not a CDN)
also needed: mootools 1.2.x

Credits and use


It is originally based upon prOdigy's text-snow for mootools 1.11. Last Xmas, I tweaked it and made the changes to the options and snow flakes' properties and movement. However, this year I have to "festivify" a few mootools 1.2.4 sites as well - a nice opportunity to refactor and rewrite everything.

As far as I'm concerned, you are free to run and modify and use this as you deem fit. Pimp my blog if you like...

--
Merry Chrismas,
Dimitar Christoff - christoff at gmail dot com
// instigating the class over element with id="mysnow" and defaults is easy
var gaySnow = new mooSnow({
    container: $("mysnow")
});
// so is getting rid of the snow:
gaySnow.meltSnow();
/* based upon the textSnow class for mootools 1.11 by prOdigy
   view original: http://pr0digy.com/mootools/text-snow/

   refactored for 1.2.x and modified by Dimitar Christoff
   http://fragged.org/

   last modified: 18/11/2009 01:46:27

   merry christmas! */

var mooSnow = new Class({
    Implements: [Options, Events],
    directions: ["left","right","straight"],
    snow: [],
    options: {
        container: null,
        inject: "top", // inject stage inside, top, before or after the container
        stage: {
            styles: {
                background: "none",
                width: null,
                height: null,
                display: "block",
                position: "absolute",
                overflow: "hidden"
            },
            padding: 1 // horisontal stage padding
        },
        snow:{
            amount: 10, // number of snowflakes
            speed: [1,2,3], //speed with wich individual snowflakes fall
            styles: {
                position: "absolute"
            },
            symbol: ["*"], //an array of flake symbols, html can be used as well
            color: ["#fff", "#eee", "#eeeedd"], //flake colours
            fontFamily: ['Impact', 'Times New Roman', 'Georgia'], //different flake shapes
            fontSize: [20, 22], //font size in pixels
            direction: "left", //left,right,straight
            opacity: [.3, 1], // opacity min and opacity max for flakes
            sinkSpeed: 50 //how fast the snow is falling
        }
    },

    initialize: function(options) {
        this.setOptions(options);

        this.container = document.id(this.options.container);
        if (!this.container)
            return;

        this.createStage();
        this.createSnow();
        this.timer = this.animateSnow.periodical(this.options.snow.sinkSpeed, this);
    },

    createStage: function() {
        // makes the layer over the container element which will hold the snow
        this.stage = new Element("div", {
            styles: this.options.stage.styles
        });

        var size = this.container.getSize();

        this.options.stage.styles.height = this.options.stage.styles.height || size.y.toInt();
        this.options.stage.styles.width = this.options.stage.styles.width || size.x.toInt();

        this.stage.setStyles({
            height: this.options.stage.styles.height,
            width: this.options.stage.styles.width
        }).inject(this.container, this.options.inject);
    },

    createSnow: function() {
        // creates all the snowflakes and assigns them size, colour, opacity and direction
        var stagePadding = this.options.stage.styles.width / 100 * this.options.stage.padding;
        var stepX = (this.options.stage.styles.width - stagePadding / 2) / this.options.snow.amount, stepY = 0;
        var posX = stepX/2, posY = 0;
        var variateX = [stepX/-3, stepX/3];

        for (i = 0; i < this.options.snow.amount; i++) {
            if(stepY >= 100) stepY = 0;
            posY = this.options.stage.styles.height/-100*stepY;
            stepY += 25;

            this.snow.push(new Element("div", {
                styles: $merge({
                    fontFamily: this.options.snow.fontFamily.getRandom(),
                    fontSize: this.options.snow.fontSize.getRandom(),
                    color: this.options.snow.color.getRandom(),
                    top: posY,
                    left: posX
                }, this.options.snow.styles),
                html: this.options.snow.symbol.getRandom(),
                opacity: (this.options.snow.opacity.length) ? $random(this.options.snow.opacity[0]*10, this.options.snow.opacity[1]*10) / 10 : this.options.snow.opacity
            }).store("direction", this.directions.getRandom()).inject(this.stage));

            posX += stepX + variateX.getRandom();
        }
    },

    animateSnow: function() {
        // draw world - do all the snowflakes
        var floor = this.options.stage.styles.height;
        var stagePadding = this.options.stage.styles.width/100*this.options.stage.padding;

        if (!this.snow.length) {
            $clear(this.timer);
            return;
        }

        this.snow.each(function(flake, i) {
            var top = flake.getStyle('top').toInt() + this.options.snow.speed.getRandom();
            top = top >= floor ? 0 : top;
            flake.setStyle('top', top);

            var moveDirection = flake.retrieve("direction");
            if (moveDirection == 'left') {
                var left = flake.getStyle('left').toInt() - [1,2].getRandom();
                left = (left < stagePadding /2) ? this.options.stage.styles.width - stagePadding/2 : left;
            } else if (moveDirection == 'right '){
                var left = flake.getStyle('left').toInt() + 1;
                left = (left > this.options.stage.styles.width - stagePadding/2) ? stagePadding/2 : left;
            } else {
                var left = flake.getStyle('left').toInt();
            }

            flake.setStyle('left', left);

        }, this);
    },

    meltSnow: function() {
        // you can stop it if you want and start again.
        this.snow.each(function(flake, i) {
            (function() {
                flake.fade(0);
                (function() {
                    flake.dispose();
                    this.snow.erase(flake);
                }).delay(100*i+500, this);
            }).delay(100*i, this);


        }, this);
    }
});