用HTML5中的Canvas结合公式绘制粒子运动的教程,粒
分类:前端技术

canvas学习笔记:小公式大野趣

2014/03/20 · HTML5 · 1 评论 · HTML5

原稿出处: WAxes   

那二日想弄二个网页,把团结学HTML5进度中做的一部分DEMO放上去做集结,可是,要是就只是做个网页把拥有DEMO一个三个排列又感觉太不要脸了。就想,既然学了canvas,这就来折腾下浏览器,做个十分小开场动画吧。

开场动画的法力,想了一会,决定用粒子,因为感觉粒子相比风趣。还记得从前本人写的首先篇才具博文,就是讲文字图片粒子化的:文字图片粒子化 , 那时候就唯有做的是直线运动,顺便加了一些3D作用。运动公式相当的粗略。所以就想以此开场动画就做的更充沛一些吧。

先上DEMO:

效果与利益是或不是比直线的移位越来越动感呢?何况也实在很轻便,别忘了那篇博文的标题,小小滴公式,大大滴野趣。要做出如此的职能,用的就只有是我们初级中学。。只怕高级中学时候的情理知识,加速移动,减速运动的公式啦。所以的确是小小滴公式。楼主很欣赏折腾一些光彩夺目的事物,就算大概平时专门的学业上用不上,不过,那野趣确实很令人着迷啊。何况,做下那个也足以增长一下编制程序的思维手艺哈。

废话相当的少说,步向正题啦。就轻易的解释一下原理吧~~~

粒子运动的基本代码就那样一点:

JavaScript

update:function(time){ this.x = this.vx*time; this.y = this.vy*time; if(!this.globleDown&&this.y>0){ var yc = this.toy - this.y; var xc = this.tox - this.x; this.jl = Math.sqrt(xc*xc yc*yc); var za = 20; var ax = za*(xc/this.jl), ay = za*(yc/this.jl), vx = (this.vx ax*time)*0.97, vy = (this.vy ay*time)*0.97; this.vx = vx; this.vy = vy; }else { var gravity = 9.8; var vy = this.vy gravity*time; if(this.y>canvas.height){ vy = -vy*0.7; } this.vy = vy; } },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
update:function(time){
            this.x = this.vx*time;
            this.y = this.vy*time;
 
            if(!this.globleDown&&this.y>0){
                var yc = this.toy - this.y;
                var xc = this.tox - this.x;
 
                this.jl = Math.sqrt(xc*xc yc*yc);
 
                var za = 20;
 
                var ax = za*(xc/this.jl),
                    ay = za*(yc/this.jl),
                    vx = (this.vx ax*time)*0.97,
                    vy = (this.vy ay*time)*0.97;
 
                this.vx = vx;
                this.vy = vy;
 
            }else {
                var gravity = 9.8;
                var vy = this.vy gravity*time;
 
                if(this.y>canvas.height){
                    vy = -vy*0.7;
                }
 
                this.vy = vy;
            }
        },

粒子总共有三种情形,一种是自由落体,一种正是受到吸力。自由落体就不说了。说吸力从前先贴出粒子的性能:

JavaScript

var Dot = function(x,y,vx,vy,tox,toy,color){ this.x=x; this.y=y; this.vx=vx; this.vy=vy; this.nextox = tox; this.nextoy = toy; this.color = color; this.visible = true; this.globleDown = false; this.setEnd(tox , toy); } setEnd:function(tox , toy){     this.tox = tox;     this.toy = toy;     var yc = this.toy - this.y;     var xc = this.tox - this.x; },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Dot = function(x,y,vx,vy,tox,toy,color){
        this.x=x;
        this.y=y;
        this.vx=vx;
        this.vy=vy;
        this.nextox = tox;
        this.nextoy = toy;
        this.color = color;
        this.visible = true;
        this.globleDown = false;
        this.setEnd(tox , toy);
    }
 
setEnd:function(tox , toy){
    this.tox = tox;
    this.toy = toy;
    var yc = this.toy - this.y;
    var xc = this.tox - this.x;
},

x,y正是粒子的岗位,vx是粒子水平速度,vy是粒子的垂直速度,nexttox之类知道还是不知道道都不在乎,只是不常保留变量的。tox,和toy正是粒子的指标地地点。

首先,先予以负有粒子叁个目标地,这几个指标地上边再会说。也正是要粒子达到的地点,然后再定义三个变量za作为加快度,具体数值的话,就和煦多测量检验下就能够有大约参数的了,小编设成20,以为就基本上了。za是粒子和目标地之间连线的增长速度度,所以,大家由此粒子的职责和指标地的任务,通过简单的三角形函数,就可以把粒子的水准加快度和垂直加快度求出来了,就这段

JavaScript

var ax = za*(xc/this.jl), ay = za*(yc/this.jl),

1
2
var ax = za*(xc/this.jl),
  ay = za*(yc/this.jl),

有了等级次序加速度和垂直加快度后,接下去就更轻便了,间接总括水平速度和垂直速度的增量,从而改造程度速度和垂直速度的值

JavaScript

vx = (this.vx ax*time)*0.97, vy = (this.vy ay*time)*0.97;

1
2
vx = (this.vx ax*time)*0.97,
vy = (this.vy ay*time)*0.97;

据此要乘于0.97是为着模仿能量消耗,粒子才会减速。time是每一帧的年月差

测算出速度后就更新粒子地点就行了。

JavaScript

this.x = this.vx*time; this.y = this.vy*time;

1
2
this.x = this.vx*time;
this.y = this.vy*time;

因为粒子在飞行进度中,与目标地之间的连线方向是不停改动的,所以每一帧都要再度计算粒子的水平加快度和垂直加快度。

活动规律正是这样,是不是异常粗略吗。

一举手一投足规律说罢了,再扯一下上边十一分动画的切实可行落到实处啊:动画起先化,在四个离屏canvas上把想要的字也许图片画出来,然后再经过getImageData那么些方式赢得离屏canvas的像素。然后用一个巡回,把离屏canvas中有绘制的区域寻找来,因为imageData里的data值正是二个rgba数组,所以大家判别末了一个的值也正是反射率大于128正是有绘制过的区域。然后拿走该区域的xy值,为了堤防粒子对象过多导致页面卡顿,所以我们就限制一下粒子的数码,取像素的时候x值和y值每一趟递增2,进而减少粒子数量。

JavaScript

this.osCanvas = document.createElement("canvas"); var osCtx = this.osCanvas.getContext("2d"); this.osCanvas.width = 一千; this.osCanvas.height = 150; osCtx.textAlign = "center"; osCtx.textBaseline = "middle"; osCtx.font="70px 微软雅黑,石籀文 bold"; osCtx.fillStyle = "#1D181F" osCtx.fillText("WelCome" , this.osCanvas.width/2 , this.osCanvas.height/2-40); osCtx.fillText("To wAxes' HOME" , this.osCanvas.width/2 , this.osCanvas.height/2 40); var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height); dots = []; for(var x=0;x<bigImageData.width;x =2){ for(var y=0;y<bigImageData.height;y =2){ var i = (y*bigImageData.width x)*4; if(bigImageData.data[i 3]>128){ var dot = new Dot( Math.random()>0.5?Math.random()*20 10:Math.random()*20 canvas.width-40, -Math.random()*canvas.height*2, 0, 0, x (canvas.width/2-this.osCanvas.width/2), y (canvas.height/2-this.osCanvas.height/2), "rgba(" bigImageData.data[i] "," bigImageData.data[i 1] "," bigImageData.data[i 2] ",1)" ); dot.setEnd(canvas.width/2,canvas.height/2) dots.push(dot); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
this.osCanvas = document.createElement(&quot;canvas&quot;);
        var osCtx = this.osCanvas.getContext(&quot;2d&quot;);
 
        this.osCanvas.width = 1000;
        this.osCanvas.height = 150;
 
        osCtx.textAlign = &quot;center&quot;;
        osCtx.textBaseline = &quot;middle&quot;;
        osCtx.font=&quot;70px 微软雅黑,黑体 bold&quot;;
        osCtx.fillStyle = &quot;#1D181F&quot;
        osCtx.fillText(&quot;WelCome&quot; , this.osCanvas.width/2 , this.osCanvas.height/2-40);
        osCtx.fillText(&quot;To wAxes&#039; HOME&quot; , this.osCanvas.width/2 , this.osCanvas.height/2 40);
        var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);
 
        dots = [];
 
        for(var x=0;x&lt;bigImageData.width;x =2){
            for(var y=0;y&lt;bigImageData.height;y =2){
                var i = (y*bigImageData.width x)*4;
                if(bigImageData.data[i 3]&gt;128){
                    var dot = new Dot(
                        Math.random()&gt;0.5?Math.random()*20 10:Math.random()*20 canvas.width-40,
                        -Math.random()*canvas.height*2,
                        0,
                        0,
                        x (canvas.width/2-this.osCanvas.width/2),
                        y (canvas.height/2-this.osCanvas.height/2),
                        &quot;rgba(&quot; bigImageData.data[i] &quot;,&quot; bigImageData.data[i 1] &quot;,&quot; bigImageData.data[i 2] &quot;,1)&quot;
                    );
                    dot.setEnd(canvas.width/2,canvas.height/2)
                    dots.push(dot);
                }
            }
        }

透过轮回获取到粒子的任务xy值后,把岗位赋给粒子,成为粒子的指标地。然后动画起头,就能够做出文字图片粒子化的功能了。

上边贴出动画达成的js代码。如若对别的代码也会有意思味的,能够直接看调控台哈,没压缩的。

JavaScript

var part_1 = (function(w){ var dots = [],DOT_SIZE = 2,cube=null; var Dot = function(x,y,vx,vy,tox,toy,color){ this.x=x; this.y=y; this.vx=vx; this.vy=vy; this.nextox = tox; this.nextoy = toy; this.color = color; this.visible = true; this.globleDown = false; this.setEnd(tox , toy); } Dot.prototype = { paint:function(){ ctx.fillStyle=this.color; ctx.fillRect(this.x-DOT_SIZE/2 , this.y-DOT_SIZE/2 , DOT_SIZE , DOT_SIZE); }, setEnd:function(tox , toy){ this.tox = tox; this.toy = toy; var yc = this.toy - this.y; var xc = this.tox - this.x; // this.initjl = Math.sqrt(xc*xc yc*yc); }, update:function(time){ this.x = this.vx*time; this.y = this.vy*time; if(!this.globleDown&&this.y>0){ var yc = this.toy - this.y; var xc = this.tox - this.x; this.jl = Math.sqrt(xc*xc yc*yc); var za = 20; var ax = za*(xc/this.jl), ay = za*(yc/this.jl), vx = (this.vx ax*time)*0.97, vy = (this.vy ay*time)*0.97; this.vx = vx; this.vy = vy; // if(Math.abs(this.vx)<1&&Math.abs(this.vy)<1){ // this.y = this.toy // this.x = this.tox // } }else { var gravity = 9.8; var vy = this.vy gravity*time; if(this.y>canvas.height){ vy = -vy*0.7; } this.vy = vy; } }, loop:function(time){ this.update(time); this.paint(); } } var animate = function(){ this.state = "before" } var ap = animate.prototype; ap.init = function(){ this.osCanvas = document.createElement("canvas"); var osCtx = this.osCanvas.getContext("2d"); this.osCanvas.width = 一千; this.osCanvas.height = 150; osCtx.textAlign = "center"; osCtx.textBaseline = "middle"; osCtx.font="70px 微软雅黑,石籀文 bold"; osCtx.fillStyle = "#1D181F" osCtx.fillText("WelCome" , this.osCanvas.width/2 , this.osCanvas.height/2-40); osCtx.fillText("To wAxes' HOME" , this.osCanvas.width/2 , this.osCanvas.height/2 40); var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height); dots = []; for(var x=0;x<bigImageData.width;x =2){ for(var y=0;y<bigImageData.height;y =2){ var i = (y*bigImageData.width x)*4; if(bigImageData.data[i 3]>128){ var dot = new Dot( Math.random()>0.5?Math.random()*20 10:Math.random()*20 canvas.width-40, -Math.random()*canvas.height*2, 0, 0, x (canvas.width/2-this.osCanvas.width/2), y (canvas.height/2-this.osCanvas.height/2), "rgba(" bigImageData.data[i] "," bigImageData.data[i 1] "," bigImageData.data[i 2] ",1)" ); dot.setEnd(canvas.width/2,canvas.height/2) dots.push(dot); } } } console.log(dots.length) } ap.changeState = function(){ var osCtx = this.osCanvas.getContext("2d"); osCtx.clearRect(0,0,this.osCanvas.width,this.osCanvas.height); this.osCanvas.width = 460; this.osCanvas.height = 100; osCtx.fillStyle="#5C5656" osCtx.fillRect(20,20,60,60) drawLogo(this.osCanvas , osCtx); var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height); var index=0; dots.sort(function(a , b){ return Math.random()-Math.random(); }) for(var x=0;x<bigImageData.width;x =2){ for(var y=0;y<bigImageData.height;y =2){ var i = (y*bigImageData.width x)*4; if(bigImageData.data[i 3]>128){ var d = dots[index]; if(d){ d.setEnd(x (canvas.width/2-300) , y 50) d.color = "rgba(" bigImageData.data[i] "," bigImageData.data[i 1] "," bigImageData.data[i 2] ",1)"; index } } } } setTimeout(function(){ var endindex = index; for(var i=0;i<dots.length-endindex;i ){ if(dots[index]){ var d = dots[index]; d.globleDown = true; d.vx = Math.random()*100-50; } index ; } } , 2000) } function endState(){ canvas.width = 600; canvas.height = 100; canvas.style.display="block"; canvas.style.top = "50px"; canvas.style.left = (window.innerWidth-canvas.width)/2 "px"; cube = new Cube(50); cube._initVector(50,50); } function drawLogo(canvas , ctx){ ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.font="65px 微软雅黑,金鼎文 bold" ctx.fillStyle="#E06D2F" ctx.fillText("DEMO" , 300 , canvas.height/2) ctx.font="40px 微软雅黑,钟鼓文 bold" ctx.fillStyle="#405159" ctx.fillText("吖猩的" , 160 , canvas.height/2) ctx.fillText("小窝" , 420 , canvas.height/2) } var num = 0; ap.update = function(time){ time = time/100; if(this.state==="first"||this.state==="before"){ var completeNum = 0; dots.forEach(function(dot){ if(dot.visible) dot.loop(time); if(dot.jl<5){ completeNum } }); if(completeNum>=5*dots.length/6){ if(this.state==="before"){ this.state = "first"; dots.forEach(function(dot){ dot.setEnd(dot.nextox , dot.nextoy); }); }else { this.state = "second"; this.changeState(); } } }else if(this.state==="second"){ var completeNum = 0, allnum = 0; dots.forEach(function(dot){ if(dot.visible) dot.loop(time); if(dot.globleDown){ allnum ; if(Math.abs(dot.y-canvas.height)<2){ completeNum } } }); if(completeNum===allnum&&allnum!==0){ this.state = "third"; part_2.animate(); endState(); } }else if(this.state==="third"){ cube.update(); drawLogo(canvas , ctx); } } return new animate(); })(window)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
var part_1 = (function(w){
    var dots = [],DOT_SIZE = 2,cube=null;
 
    var Dot = function(x,y,vx,vy,tox,toy,color){
        this.x=x;
        this.y=y;
        this.vx=vx;
        this.vy=vy;
        this.nextox = tox;
        this.nextoy = toy;
        this.color = color;
        this.visible = true;
        this.globleDown = false;
        this.setEnd(tox , toy);
    }
 
    Dot.prototype = {
        paint:function(){
            ctx.fillStyle=this.color;
            ctx.fillRect(this.x-DOT_SIZE/2 , this.y-DOT_SIZE/2 , DOT_SIZE , DOT_SIZE);
        },
 
        setEnd:function(tox , toy){
            this.tox = tox;
            this.toy = toy;
            var yc = this.toy - this.y;
            var xc = this.tox - this.x;
            // this.initjl = Math.sqrt(xc*xc yc*yc);
        },
 
        update:function(time){
            this.x = this.vx*time;
            this.y = this.vy*time;
 
            if(!this.globleDown&amp;&amp;this.y&gt;0){
                var yc = this.toy - this.y;
                var xc = this.tox - this.x;
 
                this.jl = Math.sqrt(xc*xc yc*yc);
 
                var za = 20;
 
                var ax = za*(xc/this.jl),
                    ay = za*(yc/this.jl),
                    vx = (this.vx ax*time)*0.97,
                    vy = (this.vy ay*time)*0.97;
 
                this.vx = vx;
                this.vy = vy;
 
                // if(Math.abs(this.vx)&lt;1&amp;&amp;Math.abs(this.vy)&lt;1){
                //     this.y = this.toy
                //     this.x = this.tox
                // }
            }else {
                var gravity = 9.8;
                var vy = this.vy gravity*time;
 
                if(this.y&gt;canvas.height){
                    vy = -vy*0.7;
                }
 
                this.vy = vy;
            }
        },
 
        loop:function(time){
            this.update(time);
            this.paint();
        }
    }
 
    var animate = function(){
        this.state = &quot;before&quot;
    }
 
    var ap = animate.prototype;
 
    ap.init = function(){
        this.osCanvas = document.createElement(&quot;canvas&quot;);
        var osCtx = this.osCanvas.getContext(&quot;2d&quot;);
 
        this.osCanvas.width = 1000;
        this.osCanvas.height = 150;
 
        osCtx.textAlign = &quot;center&quot;;
        osCtx.textBaseline = &quot;middle&quot;;
        osCtx.font=&quot;70px 微软雅黑,黑体 bold&quot;;
        osCtx.fillStyle = &quot;#1D181F&quot;
        osCtx.fillText(&quot;WelCome&quot; , this.osCanvas.width/2 , this.osCanvas.height/2-40);
        osCtx.fillText(&quot;To wAxes&#039; HOME&quot; , this.osCanvas.width/2 , this.osCanvas.height/2 40);
        var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);
 
        dots = [];
 
        for(var x=0;x&lt;bigImageData.width;x =2){
            for(var y=0;y&lt;bigImageData.height;y =2){
                var i = (y*bigImageData.width x)*4;
                if(bigImageData.data[i 3]&gt;128){
                    var dot = new Dot(
                        Math.random()&gt;0.5?Math.random()*20 10:Math.random()*20 canvas.width-40,
                        -Math.random()*canvas.height*2,
                        0,
                        0,
                        x (canvas.width/2-this.osCanvas.width/2),
                        y (canvas.height/2-this.osCanvas.height/2),
                        &quot;rgba(&quot; bigImageData.data[i] &quot;,&quot; bigImageData.data[i 1] &quot;,&quot; bigImageData.data[i 2] &quot;,1)&quot;
                    );
                    dot.setEnd(canvas.width/2,canvas.height/2)
                    dots.push(dot);
                }
            }
        }
        console.log(dots.length)
    }
 
    ap.changeState = function(){
        var osCtx = this.osCanvas.getContext(&quot;2d&quot;);
        osCtx.clearRect(0,0,this.osCanvas.width,this.osCanvas.height);
        this.osCanvas.width = 460;
        this.osCanvas.height = 100;
 
        osCtx.fillStyle=&quot;#5C5656&quot;
        osCtx.fillRect(20,20,60,60)
 
        drawLogo(this.osCanvas , osCtx);
 
        var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);
 
        var index=0;
        dots.sort(function(a , b){
            return Math.random()-Math.random();
        })
        for(var x=0;x&lt;bigImageData.width;x =2){
            for(var y=0;y&lt;bigImageData.height;y =2){
                var i = (y*bigImageData.width x)*4;
                if(bigImageData.data[i 3]&gt;128){
                        var d = dots[index];
                        if(d){
                            d.setEnd(x (canvas.width/2-300) , y 50)
                            d.color = &quot;rgba(&quot; bigImageData.data[i] &quot;,&quot; bigImageData.data[i 1] &quot;,&quot; bigImageData.data[i 2] &quot;,1)&quot;;
                            index
                        }
                }
            }
        }
 
        setTimeout(function(){
            var endindex = index;
            for(var i=0;i&lt;dots.length-endindex;i ){
                if(dots[index]){
                    var d = dots[index];
 
                    d.globleDown = true;
                    d.vx = Math.random()*100-50;
                }
                index ;
            }
        } , 2000)
    }
 
    function endState(){
        canvas.width = 600;
        canvas.height = 100;
        canvas.style.display=&quot;block&quot;;
        canvas.style.top = &quot;50px&quot;;
        canvas.style.left = (window.innerWidth-canvas.width)/2 &quot;px&quot;;
        cube = new Cube(50);
        cube._initVector(50,50);
    }
 
    function drawLogo(canvas , ctx){
        ctx.textAlign = &quot;center&quot;;
        ctx.textBaseline = &quot;middle&quot;;
        ctx.font=&quot;65px 微软雅黑,黑体 bold&quot;
        ctx.fillStyle=&quot;#E06D2F&quot;
        ctx.fillText(&quot;DEMO&quot; , 300 , canvas.height/2)
 
        ctx.font=&quot;40px 微软雅黑,黑体 bold&quot;
        ctx.fillStyle=&quot;#405159&quot;
        ctx.fillText(&quot;吖猩的&quot; , 160 , canvas.height/2)
        ctx.fillText(&quot;小窝&quot; , 420 , canvas.height/2)
    }
 
    var num = 0;
    ap.update = function(time){
        time = time/100;
        if(this.state===&quot;first&quot;||this.state===&quot;before&quot;){
            var completeNum = 0;
            dots.forEach(function(dot){
                if(dot.visible) dot.loop(time);
                if(dot.jl&lt;5){
                    completeNum
                }
            });
            if(completeNum&gt;=5*dots.length/6){
 
                if(this.state===&quot;before&quot;){
                    this.state = &quot;first&quot;;
                    dots.forEach(function(dot){
                        dot.setEnd(dot.nextox , dot.nextoy);
                    });
                }else {
                    this.state = &quot;second&quot;;
                    this.changeState();
                }
            }
        }else if(this.state===&quot;second&quot;){
            var completeNum = 0,
                allnum = 0;
            dots.forEach(function(dot){
                if(dot.visible) dot.loop(time);
                if(dot.globleDown){
                    allnum ;
                    if(Math.abs(dot.y-canvas.height)&lt;2){
                        completeNum
                    }
                }
            });
 
            if(completeNum===allnum&amp;&amp;allnum!==0){
                this.state = &quot;third&quot;;
                part_2.animate();
                endState();
            }
        }else if(this.state===&quot;third&quot;){
            cube.update();
            drawLogo(canvas , ctx);
        }
    }
 
    return new animate();
})(window)

赞 1 收藏 1 评论

图片 1

用HTML5中的Canvas结合公式绘制粒子运动的学科,html5canvas

这篇小说重要介绍了用HTML5中的Canvas结合公式绘制粒子运动的科目,何况要求利用Javascript代码作为公式,需求的仇敌可以参谋下

不久前想弄贰个网页,把温馨学HTML5进程中做的某个DEMO放上去做集结,可是,若是就独自做个网页把装有DEMO三个二个排列又感到太丢人了。就想,既然学了canvas,那就来折腾下浏览器,做个细微开场动画吧。

开场动画的效应,想了一会,决定用粒子,因为觉得粒子对比有趣。还记得从前笔者写的首先篇技能博文,正是讲文字图片粒子化的:文字图片粒子化 , 那时候就只有做的是直线运动,顺便加了少数3D效用。运动公式很轻易。所以就想以此开场动画就做的更充沛一些吧。

先上DEMO:

职能是或不是比直线的移位进一步精神呢?并且也的确不会细小略,别忘了那篇博文的难题,小小滴公式,大大滴野趣。要做出那样的效果与利益,用的就独有是我们初级中学。。可能高级中学时候的大意知识,加速移动,减速运动的公式啦。所以的确是小小滴公式。楼主很欣赏折腾一些粲焕的事物,固然大概日常干活上用不上,可是,那野趣确实很令人着迷啊。并且,做下那几个也能够进步级中学一年级下编制程序的思维技巧哈。

废话十分少说,进入正题啦。就归纳的解释一下原理吧~~~

粒子运动的主导代码就这么一点:  

XML/HTML Code复制内容到剪贴板

  1. update:function(time){   
  2.             this.x  = this.vx*time;   
  3.             this.y  = this.vy*time;   
  4.     
  5.             if(!this.globleDown&&this.y>0){   
  6.                 var yc = this.toy - this.y;   
  7.                 var xc = this.tox - this.x;   
  8.     
  9.                 this.jl = Math.sqrt(xc*xc yc*yc);   
  10.     
  11.                 var za = 20;   
  12.     
  13.                 var ax = za*(xc/this.jl),   
  14.                     ay = za*(yc/this.jl),   
  15.                     vx = (this.vx ax*time)*0.97,   
  16.                     vy = (this.vy ay*time)*0.97;   
  17.     
  18.                 this.vx = vx;   
  19.                 this.vy = vy;   
  20.     
  21.             }else {   
  22.                 var gravity = 9.8;   
  23.                 var vy = this.vy gravity*time;   
  24.     
  25.                 if(this.y>canvas.height){   
  26.                     vy = -vy*0.7;   
  27.                 }   
  28.     
  29.                 this.vy = vy;   
  30.             }   
  31.         },   

粒子总共有两种处境,一种是自由落体,一种便是碰着吸力。自由落体就不说了。说吸力在此之前先贴出粒子的性质:  

JavaScript Code复制内容到剪贴板

  1. var Dot = function(x,y,vx,vy,tox,toy,color){   
  2.         this.x=x;   
  3.         this.y=y;   
  4.         this.vx=vx;   
  5.         this.vy=vy;   
  6.         this.nextox = tox;   
  7.         this.nextoy = toy;   
  8.         this.color = color;   
  9.         this.visible = true;   
  10.         this.globleDown = false;   
  11.         this.setEnd(tox , toy);   
  12.     }   
  13.     
  14. setEnd:function(tox , toy){   
  15.                 this.tox = tox;   
  16.                 this.toy = toy;   
  17.                 var yc = this.toy - this.y;   
  18.                 var xc = this.tox - this.x;   
  19.         },   
  20.   

x,y就是粒子的岗位,vx是粒子水平速度,vy是粒子的垂直速度,nexttox之类知不知道道都不在乎,只是临时保留变量的。tox,和toy正是粒子的指标地地点。

先是,先予以全数粒子二个指标地,这一个指标地上边再会说。也等于要粒子达到的地方,然后再定义二个变量za作为加快度,具体数值的话,就自身多测量检验下就能有大意参数的了,笔者设成20,认为就大致了。za是粒子和指标地之间连线的加快度,所以,大家透过粒子的岗位和指标地的岗位,通过轻易的三角函数,就足以把粒子的等级次序加速度和垂直加速度求出来了,就这段  

JavaScript Code复制内容到剪贴板

  1. var ax = za*(xc/this.jl),   
  2.  ay = za*(yc/this.jl),     

有了水平加速度和垂直加快度后,接下去就更简便了,直接计算水平速度和垂直速度的增量,进而改造程度速度和垂直速度的值  

XML/HTML Code复制内容到剪贴板

  1. vx = (this.vx ax*time)*0.97,   
  2. vy = (this.vy ay*time)*0.97;  

所以要乘于0.97是为了仿功用量消耗,粒子才会放缓。time是每一帧的时日差

计量出速度后就立异粒子地点就行了。  

XML/HTML Code复制内容到剪贴板

  1. this.x  = this.vx*time;   
  2. this.y  = this.vy*time;  

因为粒子在航空进度中,与指标地之间的连线方向是不停更改的,所以每一帧都要重新计算粒子的品位加速度和垂直加快度。

挪动规律就是这么,是不是很简短吗。

移步规律说罢了,再扯一下方面拾贰分动画的具体贯彻呢:动画初叶化,在三个离屏canvas上把想要的字可能图片画出来,然后再经过getImageData那几个法子获得离屏canvas的像素。然后用贰个周而复始,把离屏canvas中有绘制的区域搜索来,因为imageData里的data值便是三个rgba数组,所以大家推断最后四个的值也等于折射率大于128正是有绘制过的区域。然后拿走该区域的xy值,为了防范粒子对象过多导致页面卡顿,所以我们就限制一下粒子的数据,取像素的时候x值和y值每一趟递增2,进而减少粒子数量。  

XML/HTML Code复制内容到剪贴板

  1. this.osCanvas = document.createElement("canvas");   
  2.         var osCtx = this.osCanvas.getContext("2d");   
  3.     
  4.         this.osCanvas.width = 1000;   
  5.         this.osCanvas.height = 150;   
  6.     
  7.         osCtx.textAlign = "center";   
  8.         osCtx.textBaseline = "middle";   
  9.         osCtx.font="70px 微软雅黑,草书 bold";   
  10.         osCtx.fillStyle = "#1D181F"  
  11.         osCtx.fillText("WelCome" , this.osCanvas.width/2 , this.osCanvas.height/2-40);   
  12.         osCtx.fillText("To wAxes' HOME" , this.osCanvas.width/2 , this.osCanvas.height/2 40);   
  13.         var bigImageData = osCtx.getImageData(0,0,this.osCanvas.width,this.osCanvas.height);   
  14.     
  15.         dots = [];   
  16.     
  17.         for(var x=0;x<bigImageData.width;x =2){   
  18.             for(var y=0;y<bigImageData.height;y =2){   
  19.                 var i = (y*bigImageData.width   x)*4;   
  20.                 if(bigImageData.data[i 3]>128){   
  21.                     var dot = new Dot(   
  22.                         Math.random()>0.5?Math.random()*20 10:Math.random()*20 canvas.width-40,   
  23.                         -Math.random()*canvas.height*2,   
  24.                         0,   
  25.                         0,   
  26.                         x (canvas.width/2-this.osCanvas.width/2),   
  27.                         y (canvas.height/2-this.osCanvas.height/2),   
  28.                         "rgba(" bigImageData.data[i] "," bigImageData.data[i 1] "," bigImageData.data[i 2] ",1)"   
  29.                     );   
  30.                     dot.setEnd(canvas.width/2,canvas.height/2)   
  31.                     dots.push(dot);   
  32.                 }   
  33.             }   
  34.         }   

经过巡回获取到粒子的地方xy值后,把地方赋给粒子,成为粒子的指标地。然后动画开端,就足以做出文字图片粒子化的机能了。

那篇作品重要介绍了用HTML第55中学的Canvas结合公式绘制粒子运动的学科,何况供给使用J...

//获取成分

var canvas = document.getElementById('canvas');

var ctx = canvas.getContext('2d');

var cw = document.documentElement.clientWidth;

var ch = document.documentElement.clientHeight;

canvas.width = cw;

canvas.height = ch;

//初始的HTML5文本

ctx.save();

ctx.font = "300px 黑体";

ctx.fillStyle = "white";

ctx.textAlign = "center";

ctx.textBaseline = "middle";

ctx.fillText("小伍哥",cw/2,ch/2);

ctx.restore();

//随机函数

function rnd(min,max) {return parseInt(Math.random()*(max-min)) min;}

//装载粒子的数组

var partciles = [];

//创制粒子

function Dot(x,y) {

//抽样像素的坐标

this.x = x;

this.y = y;

//开端的任性地方

this.startX = rnd(0,cw);

this.startY = rnd(0,ch);

//颜色

this.color = "rgb(" rnd(0,255) "," rnd(0,255) "," rnd(0,255) ")";

// this.color = "green";

//半径

this.radius = 4;

//分多少步走完

this.duration = 50;

//标志动画运行的次数

this.count = 0;

//每一回的增量

this.deltaX = (this.x - this.startX)/this.duration;

this.deltaY = (this.y - this.startY)/this.duration;

}

//绘制粒子

Dot.prototype.draw = function() {

ctx.save();

ctx.beginPath();

ctx.fillStyle = this.color;

ctx.arc(this.startX,this.startY,this.radius,0,Math.PI*2,false);

ctx.closePath();

ctx.fill();

ctx.restore();

}

//更新粒子

Dot.prototype.update = function() {

//更新坐标

this.count ;

if(this.count<=this.duration) {

this.startX = this.deltaX;

this.startY = this.deltaY;

}else {

cancelAnimationFrame(raf);

}

}

///////////////////////////////////////////////////////////////////////////

//获取canvas画布上的保有像素点

var pixels = ctx.getImageData(0,0,cw,ch);

for(var x=0;x

for (var y=0;y

//求当前点在pixels.data下的新民主主义革命通道的下标

var pos = (y*pixels.width x)*4;

if(pixels.data[pos 3]>128) {

var dot = new Dot(x,y);

partciles.push(dot);

}

}

}

///////////////////////////////////////////////////////////////////////////

//擦除画布

canvas.width = canvas.width;

//遍历装载粒子的数组

for(var i in partciles) {

var dot = partciles[i];

ctx.beginPath();

ctx.fillStyle = dot.color;

ctx.arc(dot.startX,dot.startY,dot.radius,0,Math.PI*2,false);

ctx.closePath();

ctx.fill();

}

function change() {

canvas.width = canvas.width;

raf = requestAnimationFrame(change);

for(var i in partciles) {

var dot = partciles[i];

dot.draw();

dot.update();

}

}

var raf = requestAnimationFrame(change);

效果

图片 2

图片 3

本文由pc28.am发布于前端技术,转载请注明出处:用HTML5中的Canvas结合公式绘制粒子运动的教程,粒

上一篇:html5的发展历程和由此引起的政治斗争,HTML5标准 下一篇:没有了
猜你喜欢
热门排行
精彩图文