Mega Code Archive

 
Categories / JavaScript DHTML / GUI Components
 

Snow animation

<!----------------------------------------------------------------------------------------- // XSnow für JavaScript - von Mag. Dr. Nikolaus Klepp - dr.klepp@gmx.at - www.klepp.info //-----------------------------------------------------------------------------------------   jsSnow     Copyright (C) 2002 Mag. Dr. Nikolaus Klepp   Copyright (C) 2002 INOUE Hiroyuki <dombly@kc4.so-net.ne.jp>   Copyright (C) 2002 Heiko Feldker <hfeldker@web.de>     This program is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by     the Free Software Foundation; either version 2 of the License, or     (at your option) any later version.     This program is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     GNU General Public License for more details.     You should have received a copy of the GNU General Public License     along with this program; if not, write to the Free Software     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ------------------------------------------------------------------------------------------> <HTML> <HEAD>   <!-- THE SANTA & SNOW PROGRAM -->   <script>   //--------------------------------------------------------------------------------------- // XSnow for JavaScript - von Mag. Dr. Nikolaus Klepp - dr.klepp@gmx.at - www.klepp.info //--------------------------------------------------------------------------------------- /*  jsSnow     Copyright (C) 2002 Mag. Dr. Nikolaus Klepp <dr.klepp@gmx.at>   Copyright (C) 2002 INOUE Hiroyuki <dombly@kc4.so-net.ne.jp>   Copyright (C) 2002 Heiko Feldker <hfeldker@web.de>   Release Id: 0.3n1+dombly1     This program is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by     the Free Software Foundation; either version 2 of the License, or     (at your option) any later version.     This program is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     GNU General Public License for more details.     You should have received a copy of the GNU General Public License     along with this program; if not, write to the Free Software     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //--------------------------------------------------------------------------------------- window.onerror = null; var ns6 = (!document.all && document.getElementById); var ie4 = (document.all); var ns4 = (document.layers); var BV  = (parseFloat(navigator.appVersion.indexOf("MSIE")>0 ?       navigator.appVersion.split(";")[1].substr(6)   :       navigator.appVersion)); var op  = (navigator.userAgent.indexOf('Opera')!=-1 && BV>=4); var pageWidth  = 0;            // page dimension & visible offset var pageHeight = 0; var pageOffX   = 0; var pageOffY   = 0; // <---- Customizable part ---- var flakeImageDir   = './';        // relative path for the snow flake images var santaImageDir  = './';        // relative path for Santa images var santaSize  = '2';                   // 1, 2 or 3 (smaller number specifies smaller image) var infoLayer  = 'info';        // set to false if you don't need f/s display var flakes = 25;            // total number of snowflakes var santa_mass = 5;                     // santa's effective mass during storms                                         //   specified as the ratio to snow flakes                                         //   exept 0, which means santa won't be pushed by storms var santa_speed_PperS =  20;      // santa speed in pixel/second var flake_speed_PperS =  30;      // flake speed in pixel/second var storm_speed_PperS = 300;      // storm speed in pixel/second var santa_init_x   = -256;      // santa's initial X-position var santa_direction  = 0;        // santa's movement direction in degree                     //   (between [0:360]; default is (1,0), 90 is to go up ) var santa_appearance = 0.75;      // probability between [0:1] for santa to be shown var flake_TX          = 1.0;            // max. sec. of flake's constant X-movement on fluttering var flake_XperY      = 2.0;      // fluttering movement's max. vx/vy ratio var santa_TY          = 0.5;            // max. sec. of santa's constant Y-movement in his rugged movement var santa_YperX       = 0.5;            // santa's rugged movement's max. vy/vx ratio var storm_duration_S  = 10.0;      // storm duration in seconds - watch out: about 1-2 seconds for deceleration var storm_lag_S       = 60.0;      // no-storm in seconds var storm_YperX       = 1/3.0;      // storm's max. vy/vx ratio var disappear_margin = 32;        // pixels from each border where objects disappear // ---- Customizable part ----> var refresh_FperS = 20;          // initial frames/second, recalculated. var refresh     = 1000/refresh_FperS;  // ms/frame var santa_speed   = 0;        // santa speed in pixel/frame var flake_speed   = 0;        // flake speed in pixel/frame var storm_speed   = 0;        // storm speed in pixel/frame var storm_YperX_current = storm_YperX;  // storm direction varies each time var storm_v_sin     = 0;                // storm speed's sine var storm_v_cos     = 1;                // storm speed's cosine var storm_direction = 0;        // storm X-direction, -1/0=quiet/+1 var storm_id      = 0;        // ID of storm timer var storm_blowing  = 1;        // start with storm=ON var santa; var santaX  = 0;      // X-position of santa var santaY  = 0;      // Y-position of santa var santaSY = 0;      // frames till Y-movement changes var santaVY = 0;      // variant Y-movement in pixel/frame var santaMX = 1;      // steady movement's X-ratio var santaMY = 0;      // steady movement's Y-ratio var santaDX = 0;      // X-movement in pixel/frame, caused by storm var santaDY = 0;      // Y-movement in pixel/frame, caused by storm var flake    = new Array(flakes); var flakeX   = new Array(flakes); var flakeY   = new Array(flakes); var flakeSX  = new Array(flakes); var flakeVX  = new Array(flakes); var flakeVY   = new Array(flakes); var flakeVIS = new Array(flakes); var flakeDX  = 0;      // X-movement in pixel/frame, caused by storm var flakeDY  = 0;      // Y-movement in pixel/frame, caused by storm var timer_id    = 0;    // ID if timer proc. var timer_sum   = refresh;  // Inital values for speed calculation var timer_count = 1;    // --''-- var flake_visible = op;    // start with visble flakes for Opera, all others start invisible var flake_id    = 0;    // timer id of make_flake_visible //------------------------------------------------------------------------- // preload images //------------------------------------------------------------------------- var kFlakeImages = 7; var flake_images = new Array(kFlakeImages); for(i=0;i<kFlakeImages;i++) {        flake_images[i] = new Image();   flake_images[i].src = flakeImageDir+'snow'+i+'.gif'; } var santa_image = new Image(); santa_image.src = santaImageDir+'sleigh'+santaSize+'.gif'; //------------------------------------------------------------------------- // calculates optimum framerate & corresponding speed //------------------------------------------------------------------------- function rebuild_speed_and_timer() {   var old = refresh_FperS;   refresh = Math.floor(timer_sum/timer_count*2)+10;  // ms/Frame + spare   refresh_FperS = Math.floor(1000/refresh);      // frames/second   santa_speed = santa_speed_PperS/refresh_FperS;    // pixel/second  --> pixel/frame   flake_speed = flake_speed_PperS/refresh_FperS;    // pixel/second  --> pixel/frame   storm_speed = storm_speed_PperS/refresh_FperS;     // pixel/second  --> pixel/frame   if (timer_id) window.clearInterval(timer_id);    // adapt timer   timer_id = window.setInterval('move_snow_and_santa()',refresh);   // FRAMES PER SECOND DISPLAY: REMOVE IF NOT NEEDED   if(infoLayer){     if (old!=refresh_FperS) write_to_layer(infoLayer,refresh_FperS+'f/s');   }   // adapt speed - for smoothness   if (old != refresh_FperS) {     var ratio = old/refresh_FperS;     santaVY *= ratio;     for (i=0; i<flakes; i++) {       flakeSX[i] *= ratio;       flakeVX[i] *= ratio;       flakeVY[i] *= ratio;     }   }   timer_count /= 2;  // moving medium   timer_sum   /= 2; } //------------------------------------------------------------------------- // make flakes visible: while initalialisation phase flakes are invisble. //            after make_flakes_visible, all new flakes start visible //------------------------------------------------------------------------- function make_flake_visible_proc() {   window.clearInterval(flake_id);   flake_visible = true; } //------------------------------------------------------------------------- // storm proc - turn storm on/off //------------------------------------------------------------------------- function storm_proc() {   // keep ourself from restarting while running   window.clearInterval(storm_id);   if (storm_blowing == 0) {     // turn storm on     storm_blowing = (Math.random()<0.5) ? -1 : 1 ;     storm_YperX_current = Math.random()*storm_YperX;     // prepare values by trigonometrical functions - too heavy for move_snow()     var storm_theta = Math.atan(storm_YperX_current);     storm_v_cos = Math.cos(storm_theta);     storm_v_sin = Math.sin(storm_theta);     storm_id = window.setInterval('storm_proc()',storm_duration_S*1000.0);   } else {     // turn storm off     storm_blowing *= 0.7;     if ((Math.abs(storm_blowing)<0.05) || (!flake_visible)) {       storm_blowing = 0;       storm_id = window.setInterval('storm_proc()',storm_lag_S*1000.0);     } else {       storm_id = window.setInterval('storm_proc()',500.0);     }   }   // preapare movement vektor for snow, caused by storm   flakeDX = storm_v_cos*storm_speed*storm_blowing;   flakeDY = Math.abs(storm_v_sin*storm_speed*storm_blowing);   // preapare movement vektor for santa, caused by storm & santa_mass   if(santa_mass>0) {     santaDX = flakeDX/santa_mass;     santaDY = flakeDY/santa_mass;   } else {     santaDX=0;     santaDY=0;   } } //------------------------------------------------------------------------- // create all layers & Objects //------------------------------------------------------------------------- function init_snow_and_santa() {   // create santa   santa   = get_layer_by_name('santa0');   santaX  = santa_init_x;   santaY  = Math.random()*pageHeight;   santaSY = 0;   if (santa_direction != 0) {     santaMX =  Math.cos(santa_direction/180*Math.PI);     santaMY = -Math.sin(santa_direction/180*Math.PI);   }   // create flake   for (var i=0; i<flakes; i++) {     flake[i]    = get_layer_by_name('flake'+i);     flakeX[i]   = Math.random()*pageWidth;     flakeY[i]   = Math.random()*pageHeight;     flakeSX[i]  = 0;     flakeVX[i]  = 0;     flakeVIS[i] = flake_visible;     flakeVY[i]  = 1;   } } //------------------------------------------------------------------------- // get the named layer //------------------------------------------------------------------------- function get_layer_by_name(id) {   if (op)   {  return document.getElementById(id);  }   if (ns6)  {  return document.getElementById(id);  }   if (ie4)  {  return document.all[id];      }   if (ns4)  {  return document.layers[id];      } } //------------------------------------------------------------------------- // move all objects //------------------------------------------------------------------------- function move_snow_and_santa() {   var beginn = new Date().getMilliseconds();   move_santa();   move_snow();   var ende = new Date().getMilliseconds();   var diff = (beginn>ende?1000+ende-beginn:ende-beginn);   timer_sum   += diff;   timer_count ++;   if (timer_count>10) {     rebuild_speed_and_timer();   } } //------------------------------------------------------------------------- // santa's private movement //------------------------------------------------------------------------- function move_santa() {   var lmgn = -pageWidth*(1-santa_appearance)/santa_appearance;   var rmgn = pageWidth;   var h    = pageHeight+santa_image.height;   // santa outside screen ?   if (santaX > rmgn) {     santaX  = lmgn;     santaY  = Math.random()*pageHeight;     santaSY = 0;     santaVY = 0;   } else if (santaX < lmgn) {     santaX  = rmgn;     santaY  = Math.random()*pageHeight;     santaSY = 0;     santaVY = 0;   } else if (santaY >= pageHeight) {     santaY -= h;   } else if (santaY < -santa_image.height) {     santaY += h;   } else {     santaX += santaMX * santa_speed + santaDX;     santaY += santaMY * santa_speed + santaDY;    }   // up-down-movement   santaSY --;   if (santaSY <= 0) {     santaSY = Math.random()*refresh_FperS*santa_TY;     santaVY = (2.0*Math.random()-1.0)*santa_YperX*santa_speed;   }   // move santa to new position   move_to(santa,santaX,santaY,(santaY<pageHeight- disappear_margin)); } //------------------------------------------------------------------------- // snowflake's private movement //------------------------------------------------------------------------- function move_snow() {   for (var i=0; i<flakes; i++) {     // flake outside screen ?     flakeX[i] += flakeVX[i] + flakeDX;     flakeY[i] += flakeVY[i] + flakeDY;     if (flakeY[i]>pageHeight-disappear_margin) {       flakeX[i]  = Math.random()*pageWidth;       flakeY[i]  = 0;       flakeVY[i] = flake_speed+Math.random()*flake_speed;       if (Math.random()<0.1) flakeVY[i] *= 2.0;       if (flake_visible) flakeVIS[i] = true;     }     // left-right- movement     flakeSX[i] --;     if (flakeSX[i] <= 0) {       flakeSX[i] = Math.random()*refresh_FperS*flake_TX;       flakeVX[i] = (2.0*Math.random()-1.0)*flake_XperY*flake_speed;     }     if (flakeX[i]<-disappear_margin)         flakeX[i] += pageWidth;     if (flakeX[i]>=(pageWidth-disappear_margin))       flakeX[i] -= pageWidth;     // move flake to new position     move_to(flake[i],flakeX[i],flakeY[i],flakeVIS[i]);   } } //------------------------------------------------------------------------- // move a layer //------------------------------------------------------------------------- function move_to(obj, x, y, visible) {   if (visible) {     if (op) {       obj.style.left    = x+"px";       obj.style.top     = y+"px";       // FIX THIS: SHOW DOES NOT WORK OPERA       obj.style.display   = "block";     } else if (ie4) {       obj.style.pixelLeft = x;       obj.style.pixelTop  = y;       obj.style.visibility= "visible";     } else if (ns4) {       obj.left       = x;       obj.top        = y;       obj.visibility     = "show";     } else if (ns6) {       obj.style.left     = x+"px";       obj.style.top    = y+"px";       obj.style.display   = "block";     }   } else {     if (ie4 || op) { obj.style.visibility = "hidden";}     if (ns4) { obj.visibility     = "hide";}     if (ns6) { obj.style.display   = "none";}   } } //------------------------------------------------------------------------- // fill a layer with new content // --- parameter: layer-name, new content //------------------------------------------------------------------------- function write_to_layer(layer,txt) {   if (op) {     // FIX THIS: DOES NOT WORK FOR OPERA     document.getElementById(layer).innerHTML = txt;   } else if (ie4) {     document.all[layer].innerHTML = txt;   } else if (ns4) {     document[layer].document.write(txt);     document[layer].document.close();   } else if (ns6) {     var over = document.getElementById(layer);     var range = document.createRange();     range.setStartBefore(over);     var domfrag = range.createContextualFragment(txt);     while (over.hasChildNodes()) {       over.removeChild(over.lastChild);     }     over.appendChild(domfrag);   } } //------------------------------------------------------------------------- // size of page //------------------------------------------------------------------------- function get_page_dimension() {   if(op) {     pageOffX   = 0;     pageOffY   = 25;     pageWidth  = innerWidth  + pageOffX;     pageHeight = innerHeight + pageOffY;   } else if(ns6) {     pageOffX   = scrollX;     pageOffY   = scrollY;     pageWidth  = innerWidth  + pageOffX;     pageHeight = innerHeight + pageOffY;   } else if(ns4) {     pageOffX   = window.pageXOffset;     pageOffY   = window.pageYOffset;     pageWidth  = innerWidth  + pageOffX;     pageHeight = innerHeight + pageOffY;   } else if(ie4) {     pageOffX   = document.body.scrollLeft;     pageOffY   = document.body.scrollTop;     pageWidth  = document.body.clientWidth  + pageOffX;     pageHeight = document.body.clientHeight + pageOffY;   } } //------------------------------------------------------------------------- // initialize all objects & timer //------------------------------------------------------------------------- function start() {   var a = '';      // santa's private layer   a += '<div id="santa0" '     +  'style="position: absolute; '     +  'left:-1px; top:-1px; z-index:0;">'     +  '<img src="'+santa_image.src+'"></div>\n';   // each snowflake's private layer   for (var i=0; i<flakes; i++) {     a += '<div id="flake'+i+'" '       +  'style="position: absolute; '       +  'left:-1px; top:-1px; z-index:0;">'       +  '<img src="' +flake_images[i % kFlakeImages].src+ '"></div>\n';   }   // write private layers to destination layer - this works for opera,too   document.write(a);   // recalculate page dimension every second   window.setInterval('get_page_dimension()',1000);   get_page_dimension();   // init all objects   init_snow_and_santa();   // place snowflakes, santa & trees   rebuild_speed_and_timer(refresh);   // start the animation   timer_id = window.setInterval('move_snow_and_santa()',refresh);   storm_id = window.setInterval('storm_proc()',1800);          // init with visible storm   flake_id = window.setInterval('make_flake_visible_proc()',2000);  // after the storm, let snowflakes fall :-) } /* file-variable settings for Emacsen editors   Local Variables:   tab-width: 4   End:  */   </script>   <style TITLE="Contemporary" TYPE="text/css"> body {   font-family: "Trebuchet Ms", Verdana, sans-serif;   font-weight: normal;   font-size: 10pt;   margin: 30px;   color: #c0c0c0;   background-color: #515170; } a      { color:#ffffff; text-decoration:none; font-weight:bold; } a:link    { color:#ffffff; } a:visited  { color:#ffffff; } a:active  { color:#ffffff; } a:hover    { color:#ffffff; }   </style>   <title>jsSnow - XSnow for Webpages</title> </HEAD> <BODY BGCOLOR=#515170 COLOR=#ffffff vlink=#0000ff>   <!-- FRAMES PER SECOND DISPLAY -->   <div id=info style="position:absolute; left:3px; top:3px; color:#8080ff"></div>   <!-- THIS BUILDS THE SANTA & SNOW LAYER, PLUS A NAMED CONTAINER LAYER 'santa_layer' -->   <SCRIPT>start();</SCRIPT>   <!-- REST OF PAGE -->   <DIV style="z-index:1;">   <h2>jsSnow 0.4</h2>   <h3>Hey, what's this? Looks like XSnow!</h3><br>   <img src=tannenbaum.gif style='float:left;'>   Yes, it is. I was looking for a port of my favorite toy, but didn't find any.   So I took the graphics from Rick Jansens Xsnow 1.40   (<a href=http://www.euronet.nl/~rja/>http://www.euronet.nl/~rja/</a>),   went to the kitchen, got me (Nikolaus Klepp, <a href=mailto:dr.klepp@gmx.at>dr.klepp@gmx.at</a>) a mixer, ice ... and here it is:   the first XSnow port to JavaScript! </body> </html>                          jsSnow-0.4.zip( 10 k)