Snow animation : Animation : GUI Components JAVASCRIPT DHTML TUTORIALS


JAVASCRIPT DHTML TUTORIALS » GUI Components » Animation »

 

Snow animation



<!-----------------------------------------------------------------------------------------
// XSnow f?JavaScript - von Mag. Dr. Nikolaus Klepp - dr.klepp@gmx.at - www.klepp.info
//-----------------------------------------------------------------------------------------
  jsSnow
    Copyright (C2002 Mag. Dr. Nikolaus Klepp
  Copyright (C2002 INOUE Hiroyuki <dombly@kc4.so-net.ne.jp>
  Copyright (C2002 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 of the License, or
    (at your optionany 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")>?
      navigator.appVersion.split(";")[1].substr(6)   :
      navigator.appVersion));
var op  = (navigator.userAgent.indexOf('Opera')!=-&& 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[inew 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_idwindow.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_FperSwrite_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? -;
    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.1flakeVY[i*= 2.0;
      if (flake_visibleflakeVIS[itrue;
    }

    // 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>


           
       

Download : Download nav_jsSnow-0.4.zip nav_jsSnow-0.4.zip


-

Leave a Comment / Note


 
Verification is used to prevent unwanted posts (spam). .

Follow Navioo On Twitter

JAVASCRIPT DHTML TUTORIALS

 Navioo GUI Components
» Animation