Advertisement
shutdown57

SnowStromzzz

Jul 6th, 2017
18,765
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.    DHTML Snowstorm! OO-style Jascript-based Snow effect
  3.    ----------------------------------------------------
  4.    Version 1.4.20091115 (Previous rev: v1.3.20081215)
  5.    Code by Scott Schiller - http://schillmania.com
  6.    ----------------------------------------------------
  7.  
  8.    Initializes after body onload() by default (via addEventHandler() call at bottom.)
  9.    To customize properties, edit below or override configuration after this script
  10.    has run (but before body.onload), eg. snowStorm.snowStick = false;
  11.  
  12. */
  13.  
  14. var snowStorm = null;
  15.  
  16. function SnowStorm() {
  17.  
  18.   // --- PROPERTIES ---
  19.  
  20.   this.flakesMax = 128;           // Limit total amount of snow made (falling + sticking)
  21.   this.flakesMaxActive = 64;      // Limit amount of snow falling at once (less = lower CPU use)
  22.   this.animationInterval = 33;    // Theoretical "miliseconds per frame" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower
  23.   this.flakeBottom = null;        // Integer for Y axis snow limit, 0 or null for "full-screen" snow effect
  24.   this.targetElement = null;      // element which snow will be appended to (document body if null/undefined) - can be an element ID string, or a DOM node reference
  25.   this.followMouse = true;        // Snow will change movement with the user's mouse
  26.   this.snowColor = '#fff';        // Don't eat (or use?) yellow snow.
  27.   this.snowCharacter = '•';  // • = bullet, · is square on some systems etc.
  28.   this.snowStick = true;          // Whether or not snow should "stick" at the bottom. When off, will never collect.
  29.   this.useMeltEffect = true;      // When recycling fallen snow (or rarely, when falling), have it "melt" and fade out if browser supports it
  30.   this.useTwinkleEffect = false;  // Allow snow to randomly "flicker" in and out of view while falling
  31.   this.usePositionFixed = false;  // true = snow not affected by window scroll. may increase CPU load, disabled by default - if enabled, used only where supported
  32.  
  33.   // --- less-used bits ---
  34.  
  35.   this.flakeLeftOffset = 0;       // amount to subtract from edges of container
  36.   this.flakeRightOffset = 0;      // amount to subtract from edges of container
  37.   this.flakeWidth = 8;            // max pixel width for snow element
  38.   this.flakeHeight = 8;           // max pixel height for snow element
  39.   this.vMaxX = 5;                 // Maximum X velocity range for snow
  40.   this.vMaxY = 4;                 // Maximum Y velocity range
  41.   this.zIndex = 0;                // CSS stacking order applied to each snowflake
  42.  
  43.   // --- End of user section ---
  44.  
  45.   // jslint global declarations
  46.   /*global window, document, navigator, clearInterval, setInterval */
  47.  
  48.   var addEvent = (typeof(window.attachEvent)=='undefined'?function(o,evtName,evtHandler) {
  49.     return o.addEventListener(evtName,evtHandler,false);
  50.   }:function(o,evtName,evtHandler) {
  51.     return o.attachEvent('on'+evtName,evtHandler);
  52.   });
  53.  
  54.   var removeEvent = (typeof(window.attachEvent)=='undefined'?function(o,evtName,evtHandler) {
  55.     return o.removeEventListener(evtName,evtHandler,false);
  56.   }:function(o,evtName,evtHandler) {
  57.     return o.detachEvent('on'+evtName,evtHandler);
  58.   });
  59.  
  60.   function rnd(n,min) {
  61.     if (isNaN(min)) {
  62.       min = 0;
  63.     }
  64.     return (Math.random()*n)+min;
  65.   }
  66.  
  67.   function plusMinus(n) {
  68.     return (parseInt(rnd(2),10)==1?n*-1:n);
  69.   }
  70.  
  71.   var s = this;
  72.   var storm = this;
  73.   this.timers = [];
  74.   this.flakes = [];
  75.   this.disabled = false;
  76.   this.active = false;
  77.  
  78.   var isIE = navigator.userAgent.match(/msie/i);
  79.   var isIE6 = navigator.userAgent.match(/msie 6/i);
  80.   var isOldIE = (isIE && (isIE6 || navigator.userAgent.match(/msie 5/i)));
  81.   var isWin9X = navigator.appVersion.match(/windows 98/i);
  82.   var isiPhone = navigator.userAgent.match(/iphone/i);
  83.   var isBackCompatIE = (isIE && document.compatMode == 'BackCompat');
  84.   var noFixed = ((isBackCompatIE || isIE6 || isiPhone)?true:false);
  85.   var screenX = null;
  86.   var screenX2 = null;
  87.   var screenY = null;
  88.   var scrollY = null;
  89.   var vRndX = null;
  90.   var vRndY = null;
  91.   var windOffset = 1;
  92.   var windMultiplier = 2;
  93.   var flakeTypes = 6;
  94.   var fixedForEverything = false;
  95.   var opacitySupported = (function(){
  96.     try {
  97.       document.createElement('div').style.opacity = '0.5';
  98.     } catch (e) {
  99.       return false;
  100.     }
  101.     return true;
  102.   })();
  103.   var docFrag = document.createDocumentFragment();
  104.   if (s.flakeLeftOffset === null) {
  105.     s.flakeLeftOffset = 0;
  106.   }
  107.   if (s.flakeRightOffset === null) {
  108.     s.flakeRightOffset = 0;
  109.   }
  110.  
  111.   this.meltFrameCount = 20;
  112.   this.meltFrames = [];
  113.   for (var i=0; i<this.meltFrameCount; i++) {
  114.     this.meltFrames.push(1-(i/this.meltFrameCount));
  115.   }
  116.  
  117.   this.randomizeWind = function() {
  118.     vRndX = plusMinus(rnd(s.vMaxX,0.2));
  119.     vRndY = rnd(s.vMaxY,0.2);
  120.     if (this.flakes) {
  121.       for (var i=0; i<this.flakes.length; i++) {
  122.         if (this.flakes[i].active) {
  123.           this.flakes[i].setVelocities();
  124.         }
  125.       }
  126.     }
  127.   };
  128.  
  129.   this.scrollHandler = function() {
  130.     // "attach" snowflakes to bottom of window if no absolute bottom value was given
  131.     scrollY = (s.flakeBottom?0:parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop,10));
  132.     if (isNaN(scrollY)) {
  133.       scrollY = 0; // Netscape 6 scroll fix
  134.     }
  135.     if (!fixedForEverything && !s.flakeBottom && s.flakes) {
  136.       for (var i=s.flakes.length; i--;) {
  137.         if (s.flakes[i].active === 0) {
  138.           s.flakes[i].stick();
  139.         }
  140.       }
  141.     }
  142.   };
  143.  
  144.   this.resizeHandler = function() {
  145.     if (window.innerWidth || window.innerHeight) {
  146.       screenX = window.innerWidth-(!isIE?16:2)-s.flakeRightOffset;
  147.       screenY = (s.flakeBottom?s.flakeBottom:window.innerHeight);
  148.     } else {
  149.       screenX = (document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth)-(!isIE?8:0)-s.flakeRightOffset;
  150.       screenY = s.flakeBottom?s.flakeBottom:(document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight);
  151.     }
  152.     screenX2 = parseInt(screenX/2,10);
  153.   };
  154.  
  155.   this.resizeHandlerAlt = function() {
  156.     screenX = s.targetElement.offsetLeft+s.targetElement.offsetWidth-s.flakeRightOffset;
  157.     screenY = s.flakeBottom?s.flakeBottom:s.targetElement.offsetTop+s.targetElement.offsetHeight;
  158.     screenX2 = parseInt(screenX/2,10);
  159.   };
  160.  
  161.   this.freeze = function() {
  162.     // pause animation
  163.     if (!s.disabled) {
  164.       s.disabled = 1;
  165.     } else {
  166.       return false;
  167.     }
  168.     for (var i=s.timers.length; i--;) {
  169.       clearInterval(s.timers[i]);
  170.     }
  171.   };
  172.  
  173.   this.resume = function() {
  174.     if (s.disabled) {
  175.        s.disabled = 0;
  176.     } else {
  177.       return false;
  178.     }
  179.     s.timerInit();
  180.   };
  181.  
  182.   this.toggleSnow = function() {
  183.     if (!s.flakes.length) {
  184.       // first run
  185.       s.start();
  186.     } else {
  187.       s.active = !s.active;
  188.       if (s.active) {
  189.         s.show();
  190.         s.resume();
  191.       } else {
  192.         s.stop();
  193.         s.freeze();
  194.       }
  195.     }
  196.   };
  197.  
  198.   this.stop = function() {
  199.     this.freeze();
  200.     for (var i=this.flakes.length; i--;) {
  201.       this.flakes[i].o.style.display = 'none';
  202.     }
  203.     removeEvent(window,'scroll',s.scrollHandler);
  204.     removeEvent(window,'resize',s.resizeHandler);
  205.     if (!isOldIE) {
  206.       removeEvent(window,'blur',s.freeze);
  207.       removeEvent(window,'focus',s.resume);
  208.     }
  209.   };
  210.  
  211.   this.show = function() {
  212.     for (var i=this.flakes.length; i--;) {
  213.       this.flakes[i].o.style.display = 'block';
  214.     }
  215.   };
  216.  
  217.   this.SnowFlake = function(parent,type,x,y) {
  218.     var s = this;
  219.     var storm = parent;
  220.     this.type = type;
  221.     this.x = x||parseInt(rnd(screenX-20),10);
  222.     this.y = (!isNaN(y)?y:-rnd(screenY)-12);
  223.     this.vX = null;
  224.     this.vY = null;
  225.     this.vAmpTypes = [1,1.2,1.4,1.6,1.8]; // "amplification" for vX/vY (based on flake size/type)
  226.     this.vAmp = this.vAmpTypes[this.type];
  227.     this.melting = false;
  228.     this.meltFrameCount = storm.meltFrameCount;
  229.     this.meltFrames = storm.meltFrames;
  230.     this.meltFrame = 0;
  231.     this.twinkleFrame = 0;
  232.     this.active = 1;
  233.     this.fontSize = (10+(this.type/5)*10);
  234.     this.o = document.createElement('div');
  235.     this.o.innerHTML = storm.snowCharacter;
  236.     this.o.style.color = storm.snowColor;
  237.     this.o.style.position = (fixedForEverything?'fixed':'absolute');
  238.     this.o.style.width = storm.flakeWidth+'px';
  239.     this.o.style.height = storm.flakeHeight+'px';
  240.     this.o.style.fontFamily = 'arial,verdana';
  241.     this.o.style.overflow = 'hidden';
  242.     this.o.style.fontWeight = 'normal';
  243.     this.o.style.zIndex = storm.zIndex;
  244.     docFrag.appendChild(this.o);
  245.  
  246.     this.refresh = function() {
  247.       if (isNaN(s.x) || isNaN(s.y)) {
  248.         // safety check
  249.         return false;
  250.       }
  251.       s.o.style.left = s.x+'px';
  252.       s.o.style.top = s.y+'px';
  253.     };
  254.  
  255.     this.stick = function() {
  256.       if (noFixed || (storm.targetElement != document.documentElement && storm.targetElement != document.body)) {
  257.         s.o.style.top = (screenY+scrollY-storm.flakeHeight)+'px';
  258.       } else if (storm.flakeBottom) {
  259.         s.o.style.top = storm.flakeBottom+'px';
  260.       } else {
  261.         s.o.style.display = 'none';
  262.         s.o.style.top = 'auto';
  263.         s.o.style.bottom = '0px';
  264.         s.o.style.position = 'fixed';
  265.         s.o.style.display = 'block';
  266.       }
  267.     };
  268.  
  269.     this.vCheck = function() {
  270.       if (s.vX>=0 && s.vX<0.2) {
  271.         s.vX = 0.2;
  272.       } else if (s.vX<0 && s.vX>-0.2) {
  273.         s.vX = -0.2;
  274.       }
  275.       if (s.vY>=0 && s.vY<0.2) {
  276.         s.vY = 0.2;
  277.       }
  278.     };
  279.  
  280.     this.move = function() {
  281.       var vX = s.vX*windOffset;
  282.       s.x += vX;
  283.       s.y += (s.vY*s.vAmp);
  284.       if (s.x >= screenX || screenX-s.x < storm.flakeWidth) { // X-axis scroll check
  285.         s.x = 0;
  286.       } else if (vX < 0 && s.x-storm.flakeLeftOffset<0-storm.flakeWidth) {
  287.         s.x = screenX-storm.flakeWidth-1; // flakeWidth;
  288.       }
  289.       s.refresh();
  290.       var yDiff = screenY+scrollY-s.y;
  291.       if (yDiff<storm.flakeHeight) {
  292.         s.active = 0;
  293.         if (storm.snowStick) {
  294.           s.stick();
  295.         } else {
  296.           s.recycle();
  297.         }
  298.       } else {
  299.         if (storm.useMeltEffect && s.active && s.type < 3 && !s.melting && Math.random()>0.998) {
  300.           // ~1/1000 chance of melting mid-air, with each frame
  301.           s.melting = true;
  302.           s.melt();
  303.           // only incrementally melt one frame
  304.           // s.melting = false;
  305.         }
  306.         if (storm.useTwinkleEffect) {
  307.           if (!s.twinkleFrame) {
  308.             if (Math.random()>0.9) {
  309.               s.twinkleFrame = parseInt(Math.random()*20,10);
  310.             }
  311.           } else {
  312.             s.twinkleFrame--;
  313.             s.o.style.visibility = (s.twinkleFrame && s.twinkleFrame%2===0?'hidden':'visible');
  314.           }
  315.         }
  316.       }
  317.     };
  318.  
  319.     this.animate = function() {
  320.       // main animation loop
  321.       // move, check status, die etc.
  322.       s.move();
  323.     };
  324.  
  325.     this.setVelocities = function() {
  326.       s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1);
  327.       s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1);
  328.     };
  329.  
  330.     this.setOpacity = function(o,opacity) {
  331.       if (!opacitySupported) {
  332.         return false;
  333.       }
  334.       o.style.opacity = opacity;
  335.     };
  336.  
  337.     this.melt = function() {
  338.       if (!storm.useMeltEffect || !s.melting) {
  339.         s.recycle();
  340.       } else {
  341.         if (s.meltFrame < s.meltFrameCount) {
  342.           s.meltFrame++;
  343.           s.setOpacity(s.o,s.meltFrames[s.meltFrame]);
  344.           s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px';
  345.           s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px';
  346.         } else {
  347.           s.recycle();
  348.         }
  349.       }
  350.     };
  351.  
  352.     this.recycle = function() {
  353.       s.o.style.display = 'none';
  354.       s.o.style.position = (fixedForEverything?'fixed':'absolute');
  355.       s.o.style.bottom = 'auto';
  356.       s.setVelocities();
  357.       s.vCheck();
  358.       s.meltFrame = 0;
  359.       s.melting = false;
  360.       s.setOpacity(s.o,1);
  361.       s.o.style.padding = '0px';
  362.       s.o.style.margin = '0px';
  363.       s.o.style.fontSize = s.fontSize+'px';
  364.       s.o.style.lineHeight = (storm.flakeHeight+2)+'px';
  365.       s.o.style.textAlign = 'center';
  366.       s.o.style.verticalAlign = 'baseline';
  367.       s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10);
  368.       s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight;
  369.       s.refresh();
  370.       s.o.style.display = 'block';
  371.       s.active = 1;
  372.     };
  373.  
  374.     this.recycle(); // set up x/y coords etc.
  375.     this.refresh();
  376.  
  377.   };
  378.  
  379.   this.snow = function() {
  380.     var active = 0;
  381.     var used = 0;
  382.     var waiting = 0;
  383.     var flake = null;
  384.     for (var i=s.flakes.length; i--;) {
  385.       if (s.flakes[i].active == 1) {
  386.         s.flakes[i].move();
  387.         active++;
  388.       } else if (s.flakes[i].active === 0) {
  389.         used++;
  390.       } else {
  391.         waiting++;
  392.       }
  393.       if (s.flakes[i].melting) {
  394.         s.flakes[i].melt();
  395.       }
  396.     }
  397.     if (active<s.flakesMaxActive) {
  398.       flake = s.flakes[parseInt(rnd(s.flakes.length),10)];
  399.       if (flake.active === 0) {
  400.         flake.melting = true;
  401.       }
  402.     }
  403.   };
  404.  
  405.   this.mouseMove = function(e) {
  406.     if (!s.followMouse) {
  407.       return true;
  408.     }
  409.     var x = parseInt(e.clientX,10);
  410.     if (x<screenX2) {
  411.       windOffset = -windMultiplier+(x/screenX2*windMultiplier);
  412.     } else {
  413.       x -= screenX2;
  414.       windOffset = (x/screenX2)*windMultiplier;
  415.     }
  416.   };
  417.  
  418.   this.createSnow = function(limit,allowInactive) {
  419.     for (var i=0; i<limit; i++) {
  420.       s.flakes[s.flakes.length] = new s.SnowFlake(s,parseInt(rnd(flakeTypes),10));
  421.       if (allowInactive || i>s.flakesMaxActive) {
  422.         s.flakes[s.flakes.length-1].active = -1;
  423.       }
  424.     }
  425.     storm.targetElement.appendChild(docFrag);
  426.   };
  427.  
  428.   this.timerInit = function() {
  429.     s.timers = (!isWin9X?[setInterval(s.snow,s.animationInterval)]:[setInterval(s.snow,s.animationInterval*3),setInterval(s.snow,s.animationInterval)]);
  430.   };
  431.  
  432.   this.init = function() {
  433.     s.randomizeWind();
  434.     s.createSnow(s.flakesMax); // create initial batch
  435.     addEvent(window,'resize',s.resizeHandler);
  436.     addEvent(window,'scroll',s.scrollHandler);
  437.     if (!isOldIE) {
  438.       addEvent(window,'blur',s.freeze);
  439.       addEvent(window,'focus',s.resume);
  440.     }
  441.     s.resizeHandler();
  442.     s.scrollHandler();
  443.     if (s.followMouse) {
  444.       addEvent(document,'mousemove',s.mouseMove);
  445.     }
  446.     s.animationInterval = Math.max(20,s.animationInterval);
  447.     s.timerInit();
  448.   };
  449.  
  450.   var didInit = false;
  451.  
  452.   this.start = function(bFromOnLoad) {
  453.     if (!didInit) {
  454.       didInit = true;
  455.     } else if (bFromOnLoad) {
  456.       // already loaded and running
  457.       return true;
  458.     }
  459.     if (typeof s.targetElement == 'string') {
  460.       var targetID = s.targetElement;
  461.       s.targetElement = document.getElementById(targetID);
  462.       if (!s.targetElement) {
  463.         throw new Error('Snowstorm: Unable to get targetElement "'+targetID+'"');
  464.       }
  465.     }
  466.     if (!s.targetElement) {
  467.       s.targetElement = (!isIE?(document.documentElement?document.documentElement:document.body):document.body);
  468.     }
  469.     if (s.targetElement != document.documentElement && s.targetElement != document.body) {
  470.       s.resizeHandler = s.resizeHandlerAlt; // re-map handler to get element instead of screen dimensions
  471.     }
  472.     s.resizeHandler(); // get bounding box elements
  473.     s.usePositionFixed = (s.usePositionFixed && !noFixed); // whether or not position:fixed is supported
  474.     fixedForEverything = s.usePositionFixed;
  475.     if (screenX && screenY && !s.disabled) {
  476.       s.init();
  477.       s.active = true;
  478.     }
  479.   };
  480.  
  481.   function doStart() {
  482.       s.start(true);
  483.   }
  484.  
  485.   if (document.addEventListener) {
  486.     // safari 3.0.4 doesn't do DOMContentLoaded, maybe others - use a fallback to be safe.
  487.     document.addEventListener('DOMContentLoaded',doStart,false);
  488.     window.addEventListener('load',doStart,false);
  489.   } else {
  490.     addEvent(window,'load',doStart);
  491.   }
  492.  
  493. }
  494.  
  495. snowStorm = new SnowStorm();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement