Js+canvas realize rain snow effect _javascript skill

Source: Internet
Author: User
Tags abs cos prev sin

Recently made a project, which has the need to achieve the rain snow animation effects, so this made a drop component to show this canvas common drop object effect. Before you introduce the text, first show you the effect of the picture:

Show Effect Chart:

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

Calling code

<! DOCTYPE html>
 
 

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.

Defining Global Variables

Defines two object data
//respectively is drops drop object
//And Bounce Object bounces object
var drops = [], bounces = [];
Here set the acceleration of gravity to 0.2/one frame
var gravity = 0.2;
var speed_x_x,//Transverse acceleration
speed_x_y,//longitudinal acceleration
wind_anger;//Wind Direction
//canvas pixel width high
var canvaswidth,
Canvasheight;
The probability of creating a 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, 1000/30);
};

Defining Core Objects

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 velocity object, with transverse 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 the record drop object drop speed V

var Vector = function (x, y) {
//private property transverse speed x, longitudinal velocity y
this.x = x | | 0;
This.y = y | | 0;
};
Public Method-Add: Speed change function, according to the parameters of the speed increase
//due to business needs, the consideration is the situation of drop acceleration, so there is no deceleration, the latter can be extended
* * @param v Object | | string 
*/< C10/>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: Copies a vector to be used as the record of the previous speed node
Vector.prototype.copy = function () {
//returns a vector instance
of the same speed attribute return new Vector (this.x, THIS.Y);
};
Drop drop object, that is, raindrops and snow in the effect above, you can also expand yourself into meteorites or shells.
for the drop object its basic definition 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

Constructors

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 () {
///random set initial coordinates of DROP/ 
/First randomly select whereabouts object from which side
var Randomedge = math.random () * 2;
if (Randomedge > 1) {
This.pos = new Vector (M + math.random () * canvas.width, -80);
} else{
this.pos = new Vector (Canvas.width, Math.random () * canvas.height);
Sets the size of the drop element
//The random value of the radius range of the called OPTS function
This.radius = (Opts.size_range[0] + math.random () * opts.size_range[1 ]) *DPR;
Obtain the drop initial speed
//the speed range of the called OPTS function to randomly value
This.speed = (Opts.speed[0] + math.random () * opts.speed[1)) *DPR;
This.prev = This.pos;
The angle is multiplied by 0.017453293 (2pi/360) to be converted to radians.
var eachanger = 0.017453293; 
The angle of the wind direction
Wind_anger = opts.wind_direction * Eachanger;
Obtain transverse acceleration 
speed_x = this.speed * Math.Cos (Wind_anger);
Obtain longitudinal acceleration
speed_y =-This.speed * Math.sin (Wind_anger);
Bind a speed instance
this.vel = new Vector (wind_x, wind_y);

The Update method for the Drop object

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);
};

Draw method of Drop object

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

Drop.prototype.draw = function () {
ctx.beginpath ();
Ctx.moveto (this.pos.x, this.pos.y);
There are currently only two cases, one is rain, the Bezier curve
if (Opts.type = "Rain") {
Ctx.moveto (this.prev.x, 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--, the circular 
}else{
ctx.moveto (this.pos.x, this.pos.y);
Ctx.arc (This.pos.x, This.pos.y, This.radius, 0, math.pi*2);
Ctx.fill ();
}
;

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

The definition is very simple, there is no detailed explanation

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, This.pos.y, THIS.RADIUS*DPR, 0, Math.PI * 2);
Ctx.fill ();
};

External interface

Update

Which is equivalent to the start function of 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, it is necessary to clear the instance object in the drops array if
(Drop.pos.y >= canvas.height) {
//If a rebound is required, The Bounce instance
if (opts.hasbounce) {
var n = math.round (4 + math.random () * 4) is added to the bouncess array;
while (n--)
Bounces.push (New Bounce (drop.pos.x, canvas.height));
If the drop instance drops to the bottom, the instance object
drops.splice (i, 1) needs to be clear in the drops array;
Drop.draw ();
}
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);
}
}
Number of each generated
if (Drops.length < Opts.maxnum) {
if (Math.random () < drop_chance) {
var i = 0,
len = O Pts.numlevel;
for (; i<len; i++) {
Drops.push (new Drop ());
}}} 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 the style

function init (opts) {
opts = opts;
Canvas = document.getElementById (opts.id);
CTX = Canvas.getcontext ("2d");
Compatible with the high-definition screen, canvas canvas pixels should be changed accordingly
DPR = Window.devicepixelratio;
Canvas artboard pixel size, need to be compatible with HD screen, so the canvas of the artboard should be multiplied by the DPR
canvaswidth = canvas.clientwidth * DPR;
Canvasheight =canvas.clientheight * DPR;
Set the artboard width high
canvas.width = canvaswidth;
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) ';
}
}

Conclusion

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

Finally said the inadequacy of the local and late work ha:

0, the component is not enough external interface, adjustable range is not a lot of abstraction is not very thorough

1, SetStyle set the basic style

2, drop and bounce objects of the update and draw methods of customization, so that users can set more falling speed and size change in form and style effect

3, should increase the animation of the pause, acceleration and deceleration of the operation of the interface

The above mentioned is a small set of JS and canvas to realize the effect of rain snow related knowledge, hope to help everyone, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Reproduced in this article: http://blog.csdn.net/xllily_11/article/details/51444311

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.