Canvas for stunning particle motion effects

Source: Internet
Author: User
This article mainly introduce and introduce you to the implementation of the canvas to dazzle the particle motion effect (particle generation text), small series feel very good, and now share to everyone, but also for everyone to do a reference. Follow the small series together to see it, hope to help everyone.

Directly on the code, do not understand the code comments can be seen. I guess we'll see the idea.

HTML code


<! DOCTYPE html>

The HTML code is not much, as long as there are several manipulation elements. It's clear here at a glance. Not too much of a breath. Let's take a look at the main character JavaScript code in this article, but before we look at the code, we might as well listen to the idea of achieving it:

    1. First of all, we have to be a bunch of mass actors (particles);

    2. Attach the relevant parameters of each particle to some of its properties, because the first particle will have its own trajectory;

    3. Then we have to make them move together. There are two kinds of movement (Movement of free movement and generation of text);

The JAVASCRIPT code uses three canvas canvases, This.icanvas (home), this.icanvascalculate (used to calculate the width of a text), This.icanvaspixel (used to draw the text and get the position coordinates of the pixel points corresponding to the text).

The two this.icanvascalculate and this.icanvaspixel do not need to be shown in the page, they are just auxiliary functions.

The following is a stick of the JS implementation code


function Circle () {var this = this;    This.init ();    This.generalrandomparam ();    This.drawcircles ();    This.ballanimate ();    This.getusertext ();        After changing the size of the window, the window.onresize = function () {this.statew = Document.body.offsetWidth is calculated and retrieved.        This.stateh = Document.body.offsetHeight;        THIS.ICANVASW = This.iCanvas.width = This.statew;        This.icanvash = This.iCanvas.height = This.stateh;    This.ctx = This.iCanvas.getContext ("2d");    }}//Initialization Circle.prototype.init = function () {//parent element width High this.statew = document.body.offsetWidth;    This.stateh = Document.body.offsetHeight;    This.icanvas = document.createelement ("Canvas");    Set the canvas to be the same width height as the parent element THIS.ICANVASW = This.iCanvas.width = This.statew;    This.icanvash = This.iCanvas.height = This.stateh;    Get 2d painting Environment This.ctx = This.iCanvas.getContext ("2d");    Insert into BODY element document.body.appendChild (This.icanvas);    This.icanvascalculate = document.createelement ("Canvas"); Used to save the calculation textThe word width of the canvas this.mctx = This.iCanvasCalculate.getContext ("2d");    This.mCtx.font = "128px Microsoft Jas Black";    This.icanvaspixel = document.createelement ("Canvas");    This.iCanvasPixel.setAttribute ("Style", "position:absolute;top:0;left:0;"); This.pctx = null;    The number of canvases//randomly generated circles used for drawing text This.ballnumber = Ramdomnumber (1000, 2000);    Keep an array of all the balls this.balls = [];    Save the last ball in the animation stop motion this.animte = null;    This.imagedata = null; this.textwidth = 0; Saves the width of the generated text this.textheight = 150; Save the height of the generated text This.inputtext = "";    Save user-entered content this.actioncount = 0; This.ballactor = []; Save the generated text particle this.actornumber = 0; The number of particles saving generated text This.backtype = "Back"; return this.backdynamics = ""; Animation effect This.isplay = false;        Identification (cannot be regenerated during text generation)}//renders all circles Circle.prototype.drawCircles = function () {for (Var i=0;i<this.ballnumber;i++) {    This.renderball (This.balls[0]); }}//get user input text Circle.prototype.getUserText = function () {this = this;//save this point to IPU = docUment.getelementbyid ("Input-text"); Ipu.addeventlistener ("KeyDown", function (event) {if (Event.which = = = 13) {//If the return key is Ipu.value = Ipu.value. Trim (); Kinsoku space var pat =/[\u4e00-\u9fa5]/;            Chinese judgment var Ischinese = pat.test (Ipu.value);            if (ipu.value.length!=0 && ischinese) {this.inputtext = Ipu.value;                }else{alert ("Please enter Chinese characters");            Return            } if (This.isplay) {return} this.getanimatetype ();            This.gettextpixel ();        This.isplay = true; }    });} Calculates the width of the text Circle.prototype.calculateTextWidth = function () {this.textwidth = This.mCtx.measureText (this.inputtext). WI DTH;} Gets the text pixel point Circle.prototype.getTextPixel = function () {if (this.pctx) {This.pCtx.clearRect (0,0,this.textwidth,th    Is.textheight);    } this.calculatetextwidth (This.inputtext);    This.iCanvasPixel.width = This.textwidth; ThiS.icanvaspixel.height = This.textheight;    This.pctx = This.iCanvasPixel.getContext ("2d");    This.pCtx.font = "128px Microsoft Jas Black";    This.pCtx.fillStyle = "#FF0000";    This.pCtx.textBaseline = "Botom";    This.pCtx.fillText (this.inputtext,0,110);    This.imagedata = This.pCtx.getImageData (0,0,this.textwidth,this.textheight). data; This.gettextpixelposition (this.textwidth,this.textheight);}    Gets the text particle pixel point position Circle.prototype.getTextPixelPosition = function (width,height) {var left = (this.icanvasw-width)/2;    var top = (this.icanvash-height)/2;    var space = 4;    This.actioncount = 0; for (Var i=0;i<this.textheight;i+=space) {for (Var j=0;j<this.textwidth;j+=space) {var index = J*spa            ce+i*this.textwidth*4; if (this.imagedata[index] = = 255) {if (this.actioncount<this.ballnumber) {this.balls[th                    Is.actioncount].status = 1;                    This.balls[this.actioncount].targetx = Left+j; This.ballS[this.actioncount].targety = Top+i;                    This.balls[this.actioncount].backx = this.balls[this.actioncount].x;                    This.balls[this.actioncount].backy = THIS.BALLS[THIS.ACTIONCOUNT].Y;                    This.ballActor.push (This.balls[this.actioncount]);                this.actioncount++;    }}} This.actornumber = This.ballActor.length; } this.animatetotext ();} Particle motion to the specified position Circle.prototype.animateToText = function () {for (Var i=0;i<this.actornumber;i++) {Dynamics.animat            E (This.ballactor[i], {x:this.ballactor[i].targetx, y:this.ballactor[i].targety},{    Type:dynamics.easeIn, duration:1024,});    } setTimeout (function () {this.ballbacktype (); },3000);} Particle origin return Circle.prototype.ballBackPosition = function () {for (Var i=0;i<this.actornumber;i++) {var ball = this        . Ballactor[i]; Dynamics.animate (Ball, {X:balL.backx, Y:ball.backy},{type:dynamics[this.backdynamics], duration:991,    Complete:this.changeStatus (Ball)});    }}//Get Type | animation effect Circle.prototype.getAnimateType = function () {var selecttype = document.getElementById ("SelectType");    var selectdynamics = document.getElementById ("Selectdynamics");    This.backtype = Selecttype.options[selecttype.options.selectedindex].value; This.backdynamics = Selectdynamics.options[selectdynamics.options.selectedindex].value;}    Reset Diffuse Circle.prototype.ballbackType = function () {if (This.backtype = = "Back") {this.ballbackposition ();    }else{this.ballautoposition (); } this.ballactor = [];} Randomly disperse Circle.prototype.ballAutoPosition = function (ball) {for (Var i=0;i<this.actornumber;i++) {This.changest    ATUs (This.ballactor[i])}}//change pellet state Circle.prototype.changeStatus = function (ball) {ball.status = 0; if (This.isplay = = true) {This.isplay = false;   }}//randomly generates correlation parameters for each circle Circle.prototype.generalRandomParam = function () {for (Var i=0;i<this.ballnumber;i++) {var        Ball = {}; Ball.size = 1;        Randomly generated circle radius//randomly generated center x coordinate ball.x = Ramdomnumber (0+ball.size, this.icanvasw-ball.size);        Ball.y = Ramdomnumber (0+ball.size, this.icanvash-ball.size);        Ball.speedx = Ramdomnumber (-1, 1);        Ball.speedy = Ramdomnumber (-1, 1);        This.balls.push (ball);        Ball.status = 0;        Ball.targetx = 0;        ball.targety = 0;        Ball.backx = 0;    Ball.backy = 0; }}//change the position of the circle Circle.prototype.changeposition = function () {for (Var i=0;i<this.ballnumber;i++) {if (this.balls[i            ].status = = 0) {this.balls[i].x + = This.balls[i].speedx;        This.balls[i].y + = This.balls[i].speedy;    }}}//Draw Circle Circle.prototype.renderBall = function (ball) {This.ctx.fillStyle = "#fff"; This.ctx.beginPath ();    This must be added This.ctx.arc (ball.x, Ball.y, Ball.size, 0, 2 * math.pi); THis.ctx.closePath (); This must be added This.ctx.fill ();} Ball collision Judgment Circle.prototype.collision = function (balls) {for (Var i=0;i<this.ballnumber;i++) {if (ball.x>this.ic Anvasw-ball.size | |            Ball.x<ball.size) {if (ball.x>this.icanvasw-ball.size) {ball.x = this.icanvasw-ball.size;            }else{ball.x = ball.size;       } Ball.speedx =-Ball.speedx;                } if (Ball.y>this.icanvash-ball.size | | ball.y<ball.size) {if (ball.y>this.icanvash-ball.size) {            Ball.y = this.icanvash-ball.size;            }else{ball.y = ball.size;       } ball.speedy =-ball.speedy;    }}}//Start Animation Circle.prototype.ballAnimate = function () {var this = this; var animateframe = Window.requestanimationframe | | Window.mozrequestanimationframe | | Window.webkitrequestanimationframe | |    Window.msrequestanimationframe; (function Move () {Animte = Animateframe (move);       This.ctx.clearRect (0, 0, THIS.ICANVASW, This.icanvash);        This.changeposition ();           for (Var i=0;i<this.ballnumber;i++) {this.collision (this.balls[i]);        This.renderball (This.balls[i]); }    })();} Generates a random number function ramdomnumber (min, max) {return math.random () * (max-min) + min;}

Look at the code estimates are just a little in the heart, nor let you want to make this thing out of the desire, for this I know must let your eyes convinced. Online DEMO: An example of a dynamic particle.

Nobody is perfect, the code is the same. It seems that the code that runs smoothly is more or less flawed, and the effect is only supported in Chinese. In English, I have to try again, no matter what, English will definitely join, it is only a matter of time. There is also a property in the code that marks whether the generated text can be executed again: This.isplay, or a bit of a flaw, This.isplay's state change did not exactly change the moment the particle returned, but changed the state in advance. But this state does not affect the full implementation of this example effect.

This example uses the Dynamics.js library, mainly using some of its motion functions, so that particles move more moving, and that's all.

Related Article

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.