HTML5 realization of the rain/Snow instance source code

Source: Internet
Author: User
Tags abs cos prev sin

There is a recent project need to have a rain and snow animation effects, here made a drop of the component, to show this canvas common drop object effect. So, =. = Let's see the effect first.

# #效果展示

Calling code

<! doctype html> 


It rains and snows.


It looks good, and it's easier to use canvas than to create a multiple-object displacement animation with a DOM element, and better performance

# #源码讲解

Okay, so here's the simple implementation principle first, define some of the global variables we'll use, such as wind direction, probability, object data, etc.

# # #定义全局变量

Define two object data//Drops falling object///Object Bounces object var drops = [], bounces = [];
This sets the gravitational acceleration to 0.2/one frame var gravity = 0.2; var speed_x_x, //Lateral Acceleration       speed_x_y, //longitudinal acceleration        wind_anger;  //Wind/canvas pixel width high var canvaswidth,     
Canvasheight;
Probability of creating drop var drop_chance;
Configuration Object var opts; Determine if there is a Requestanimationframe method, if used, not about a second or 30 frames window.requestanimframe =     
window.requestanimationframe | |
    window.webkitrequestanimationframe | |
    window.mozrequestanimationframe | |
    window.orequestanimationframe | |
    window.msrequestanimationframe | |     function (callback)  {        
Window.settimeout (CALLBACK,&NBSP;1000&NBSP;/&NBSP;30);     }; 


# # #定义核心对象

Next we need to define a few important objects the organization needs to define fewer objects, a total of only three have defined the ' three core objects ' in the entire drop component, respectively, as follows:

         vector speed objects, with horizontal x, and longitudinal y of the Velocity size unit: V = displacement pixel/frame

The vector object's understanding is also very simple and rough, is to record the drop object drop speed/V

Var vector = function (x, y)  {    //private properties    horizontal speed x , Longitudinal Speed y     this.x = x | |
 0;     this.y = y | |
 0;
}; The public method- add :  the speed change function, according to the parameter to increase the speed//due to the business needs, the consideration is the situation of drop acceleration, so there is no deceleration, later can expand * *  @param  v   object | |  string   * Vector.prototype.add = function (v)  {    if  ( V.x != null && v.y != null)  {      
  this.x += v.x;
        this.y += v.y;     } else {        this.x += 
V
        this.y += v;
    }     return this;
}; Public method- copy :  copy a vectorTo be used as the record of the previous speed Node vector.prototype.copy = function ()  {    //
Returns a Vector instance     return new vector (THIS.X,&NBSP;THIS.Y) with an equal velocity attribute; };


Drop drop objects, that is, the effect of raindrops and snow, in the back you can expand yourself into meteorites or shells

The underlying definition for the drop object is as follows

Constructor
var Drop = function () {/
* .... */
};
Public method-update
Drop.prototype.update = function () {/
* ... */
};
Public method-draw
Drop.prototype.draw = function () {/
* ... */
};


Look at the above three methods, whether they have guessed their role, and then let us understand what these three methods do

### #构造函数

The constructor is primarily responsible for defining the initial information of the drop object, such as speed, initial coordinates, size, acceleration, etc.

Constructor  drop var drop = function ()  {    //The initial coordinates of the Drop in random setting    
   //first randomly selects the falling object from which side     var randomedge = math.random () *2;     if (randomedge > 1) {        
This.pos = new vector (50 + math.random ()  * canvas.width, -80);     }else{        this.pos = new 
Vector (Canvas.width, math.random ()  * canvas.height); &NBSP;&NBSP;&NBSP;&NBSP}     //Set the size of the drop element      // Random value of the radius range of the called OPTS function     this.radius =  (opts.size_range[0] + 
Math.random ()  * opts.size_range[1])  *DPR;     //obtains the drop initial velocity     //the random value of the speed range of the called OPTs function      this.speed =  (OPTS. Speed[0] + math.random ()  * opts.speed[1])  *DPR;
    this.prev = this.pos;
    //the angle multiplied by the  0.017453293  (2pi/360) to be converted to radians.     var eachAnger =  0.017453293;      //
Get the angle of the wind     wind_anger = OPTS.wind_direction * eachAnger;     //gain transverse acceleration       speed_x =  this.speed *
 math.cos (Wind_anger);     //Gain longitudinal acceleration     speed_y = - this.speed * 
Math.sin (Wind_anger);     //binds a speed instance     this.vel = new vector (wind_x, 
WIND_Y); };


### #Drop对象的update方法

The Update method is responsible for changing the properties of the drop instance for each frame, such as displacement

Drop.prototype.update = function () {
This.prev = this.pos.copy ();
If there is a gravity condition, the longitudinal velocity is increased if
(opts.hasgravity) {
this.vel.y + = gravity;
}
//
This.pos.add (this.vel);
};


### #Drop对象的draw方法

The draw method is responsible for painting the drop instance per frame

Drop.prototype.draw = function ()  {  ctx.beginpath ();   ctx.moveto (this.pos.x
, &NBSP;THIS.POS.Y); There are currently only two cases, one is rain  -Bezier curve   if (opts.type == "Rain") {     
  ctx.moveto (THIS.PREV.X,&NBSP;THIS.PREV.Y);        var ax = math.abs (This.radius * math.cos (
Wind_anger));        var ay = math.abs (This.radius * math.sin (
Wind_anger));        ctx.beziercurveto (this.pos.x + ax, this.pos.y +  ay, this.prev.x + ax , this.prev.y + ay, this.pos.x, 
THIS.POS.Y);
       ctx.stroke ();   //the other is snow--, which is circular         }else{     
    ctx.moveto (THIS.POS.X,&NBSP;THIS.POS.Y);          ctx.arc (This.pos.x, this.pos.y, this.radius, 0,
&NBSP;MATH.PI*2);
         ctx.fill ();   };


        Bounce Drop falling landing object, that is, the water droplets above the rain rebound, you can also expand later to bounce gravel or soot

definition is very simple, This is not a detailed description of the

Var bounce = function (x, y)  {  var dist = math.random ()
 * 7;
  var angle = math.pi + math.random ()  * Math.PI;
  this.pos = new vector (X, y);
  this.radius =  0.2+ math.random () *0.8;
  this.vel = new vector (    math.cos (angle)  * dist,
    math.sin (angle)  * dist     );
}; Bounce.prototype.update = function ()  {  this.vel.y += gravity;   
this.vel.x *= 0.95;
  this.vel.y *= 0.95;
  this.pos.add (This.vel);
}; Bounce.prototype.draw = function ()  {  ctx.beginpath ();   ctx.arc (This.pos.x,
&NBSP;THIS.POS.Y,&NBSP;THIS.RADIUS*DPR,&NBSP;0,&NBSP;MATH.PI&NBSP;*&NBSP;2);
  ctx.fill (); };


# #对外接口

# # #update

that is equivalent to the start function for the entire canvas animation

Function update ()  {    var d = new Date;    
 //Clear Paint     ctx.clearrect (0, 0, canvas.width, canvas.height);
    var i = drops.length;     while  (i--)  {        var drop
 = drops[i];
        drop.update ();         //If the drop instance drops to the bottom, you need to clear the instance object in the drops array          if  (drop.pos.y >= canvas.height)  {             //If a rebound is required, add the bounce instance to the bouncess array              if (opts.hasbounce) {                 var n = math.round (4 + MAth.random ()  * 4);                 while  ( n--)                 
Bounces.push (New bounce (drop.pos.x, canvas.height));             }             //If the drop instance drops to the bottom, you need to clear the instance object in the drops array        
     drops.splice (i, 1);
        }         drop.draw (); &NBSP;&NBSP;&NBSP;&NBSP}     //If you need to rebound     if (OPTS.hasBounce) { 
       var i = bounces.length;         while  (i--)  {             var bounce = bounces[i];
            bounce.update ();
            bounce.draw ();             if  (bounce.pos.y > 
Canvas.height)  bounces.splice (i, 1);
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP}    &nbsp}     //quantity produced each time     if (drops.length < opts.maxnum) {         if  (Math.random ()  < drop_chance)  {             var i = 0,          
         len = OPTS.numLevel;             for (;  i< len; i++) {               
 drops.push (New drop ());             }        &NBSP;&NBSP}    &nbsp}     //constant Loop update     
Requestanimframe (update); }


# # #init

Init interface, initializes all the underlying properties of the entire canvas canvas, such as getting the pixel ratio of the screen, and setting the pixel size of the canvas, and setting the style

Function init (opts)  {    OPTS = opts;     canvas
 = document.getelementbyid (opts.id);
    ctx = canvas.getcontext ("2d");     ////compatible with HD screen, canvas canvas pixel should be changed accordingly     DPR = 
Window.devicepixelratio;     //canvas artboard pixel size,  need to be compatible with HD screen, so the artboard canvas width should be multiplied by DPR     canvaswidth
 = canvas.clientWidth * DPR;
    canvasHeight =canvas.clientHeight * DPR;
    //Set artboard width     canvas.width = canvasWidth; height
    canvas.height = canvasHeight;
    drop_chance = 0.4;
    //set style     setstyle (); } function setstyle () {    if (opts.type == "Rain") {         ctx.linewidth = 1 * dpr;
        ctx.strokeStyle =  ' Rgba (223,223,223,0.6) ';
        ctx.fillStyle =  ' Rgba (223,223,223,0.6) ';     }else{        ctx.linewidth = 2
 * DPR;
        ctx.strokeStyle =  ' Rgba (254,254,254,0.8) ';
        ctx.fillStyle =  ' Rgba (254,254,254,0.8) '; &NBSP;&NBSP;&NBSP;&NBSP}}


# #结束语

OK, a simple drop component has been completed, of course, there are many places is not perfect, after the writing of the drop component, for the animation implementation of the canvas, I believe there are many places to explore in the H5 scene.

finally say the insufficient place and later work ha:

    0, the component is not enough external interface, adjustable range is not a lot, the abstract is not very thorough
    1, SetStyle sets the basic style
    2, Drop and bounce objects of the update and draw methods to customize, so that users can set more falling speed and size change in form and style effects
&NBSP;&NB sp;  3, should increase the animation of the pause, acceleration and deceleration, such as the interface of the operation of the

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.