澳门新萄京:小公式大野趣,用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 = 1000; 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 = 1000; 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. 澳门新萄京:小公式大野趣,用HTML5中的Canvas结合公式绘制粒子运动的科目。            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值后,把岗位赋给粒子,成为粒子的目标地。然后动漫开端,就足以做出文字图片粒子化的效率了。

那篇随笔主要介绍了用HTML5中的Canvas结合公式绘制粒子运动的学科,而且要求接收J...

//获取成分

用HTML5制作数字时钟的课程,html5机械钟教程

这篇小说首要介绍了用HTML5创立数字时钟的科目,首要行使HTML第55中学的Canvas API,须要的爱人能够参见下

澳门新萄京 2

便是其生龙活虎数字石英钟,那个时候感到这些创新意识不错,可是也没去折腾。直到后天同事又在网络来看这一个案例,他以为十分炫目,就跑过来问作者,那一个是怎么贯彻的,然后本人大约想了一下跌实方式后也来了点兴趣,就花了一点时刻模仿做出来了三个。差别的是,岑安用的是div来做的。而自己即是用canvas来兑现的。用canvas来做质量方面会更加好,因为就只有操控每一个点的移动,用js调整dom的style属性跟用js调控canvas绘图比较品质方面一定是具有欠缺的。

  先上个自个儿做的DEMO吧,然后再简述一下做这些的法子:   看DEMO请戳作者 。

  做那么些思路很简短,正是经过字符串保存种种数字的地点: 
复制代码

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

  1. var numData = [   
  2.             "1111/1001/1001/1001/1001/1001/1111", //0   
  3.             "0001/0001/0001/0001/0001/0001/0001", //1   
  4.             "1111/0001/0001/1111/1000/1000/1111", //2   
  5.             "1111/0001/0001/1111/0001/0001/1111", //3   
  6.             "1010/1010/1010/1111/0010/0010/0010", //4   
  7.             "1111/1000/1000/1111/0001/0001/1111", //5   
  8.             "1111/1000/1000/1111/1001/1001/1111", //6   
  9.             "1111/0001/0001/0001/0001/0001/0001", //7   
  10.             "1111/1001/1001/1111/1001/1001/1111", //8   
  11.             "1111/1001/1001/1111/0001/0001/1111", //9   
  12.             "0000/0000/0010/0000/0010/0000/0000", //:   
  13.         ]  

  0代表没像素,1表示有像素,/是为着越来越美观些,正是分行嘛,轻便聊到来:比方0正是:

  

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

  1.         1  1  1  1   
  2.   
  3.   1  0  0  1   
  4.   
  5.   1  0  0  1   
  6.   
  7.   1  0  0  1   
  8.   
  9.   1  0  0  1   
  10.   
  11.   1  0  0  1   
  12.   
  13.   1  1  1  1     

诸如此比就很明亮了啊。从0到9还也可能有二个:号都用字符串表示好。

  然后就写个粒子对象,也正是像素点:

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

  1. var P_radius = 8,Gravity = 9.8;   
  2.         var Particle = function(){   
  3.             this.x = 0;   
  4.             this.y = 0;   
  5.             this.vx = 0;   
  6.             this.vy = 0;   
  7.             this.color = "";   
  8.             this.visible = false;   
  9.             this.drop = false;   
  10.         }   
  11.         Particle.prototype = {   
  12.             constructors:Particle,   
  13.             paint:function(){        //绘制自个儿   
  14.                 ctx.fillStyle = this.color;   
  15.                 ctx.beginPath();   
  16.                 ctx.arc(this.x,this.y,P_radius,0,2*Math.PI);   
  17.                 ctx.fill();   
  18.             },   
  19.             reset:function(x,y,color){        //重置   
  20.                 this.x = x;   
  21.                 this.y = y;   
  22.                 this.vx = 0;   
  23.                 this.vy = 0;   
  24.                 this.color = color;   
  25.                 this.visible = true;   
  26.                 this.drop = false;   
  27.             },   
  28.             isDrop:function(){        //落下   
  29.                 this.drop = true;   
  30.                 var vx = Math.random()*20 15   
  31.                 this.vx = Math.random()>=0.5?-vx : vx;   
  32.             },   
  33.             update:function(time){        //每生机勃勃帧的动作   
  34.                 if(this.drop){   
  35.                     this.x  = this.vx*time;   
  36.                     this.y  = this.vy*time;   
  37.   
  38.                     var vy = this.vy Gravity*time;   
  39.   
  40.                     if(this.y>=canvas.height-P_radius){   
  41.                         this.y = canvas.height-P_radius   
  42.                         vy = -vy*0.7;   
  43.                     }   
  44.   
  45.                     this.vy = vy;   
  46.   
  47.                     if(this.x<-P_radius||this.x>canvas.width P_radius||this.y<-P_radius||this.y>canvas.height P_radius){   
  48.                         this.visible = false;   
  49.                     }   
  50.                 }   
  51.             }   
  52.         }     
  53.   

粒子对象的品质比较轻易,就地点,速度,以至是还是不是可视化。方法的话,paint是绘制方法,reset是重新初始化(因为粒子要循环使用的,提高品质卡塔尔国,isDrop是粒子落下方法,update正是每大器晚成帧更新粒子的动作,update中当粒子运动过量canvas的绘图区域时,就把它的可视化置为false,在粒子容器中保存起来等待下贰回调用。

  写好粒子对象后,将在寻思怎么着让粒子遵照岗位画上去,同期当粒子没有必要用时能够让他做自由落体的卡通片了。

  先画背景(也正是那没有像素的白点卡塔 尔(英语:State of Qatar):

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

  1. function drawBg(){   
  2.             var tx = (canvas.width-((P_radius*2 X_J)*4*8 7*xjg))/2;   
  3.             for(var i=0;i<8;i ){   
  4.                 var ty = (canvas.height-((P_radius yjg)*6))/2;   
  5.                 for(var j=0;j<numData[0]澳门新萄京,.length;j ){   
  6.                     var tt = numData[0].charAt(j);   
  7.                     if(tt==="/"){   
  8.                         ty =yjg;   
  9.                     }else {   
  10.                         var x = tx j%5*(P_radius*2 X_J),   
  11.                             y = ty;   
  12.                         bgctx.fillStyle = "#FFF";   
  13.                         bgctx.beginPath();   
  14.                         bgctx.arc(x,y,P_radius,0,2*Math.PI);   
  15.                         bgctx.fill();   
  16.                     }   
  17.                 }   
  18.                 tx =xjg 4*(P_radius*2 X_J);   
  19.             }   
  20.         }   

  先把背景画到三个离屏canvas中缓存起来,接下去每黄金年代帧重画的时候就没有须要逻辑计算了,直接把特别离屏canvas画上去就能够了。上面的逻辑应该简单领会,正是通过五个循环,循环8个数字,然后再对各类数字一个点多个点展开绘图,当蒙受“/”时,就表达要换行了,把绘制的ty加个换行间隔,再把tx重新恢复生机设置,再举行绘图。就这么,点就足以都画出来了。效果图如下:
澳门新萄京 3

背景画好了,就起来依据每生龙活虎秒的小运,画数字像素吧。方法首假使其大器晚成:

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

  1. function setTime(time){   
  2.             var h = time.getHours() "",   
  3.                 m = time.getMinutes() "",   
  4.                 s = time.getSeconds() "";   
  5.             hh = h.length===1?"0" h:h;   
  6.             mm = m.length===1?"0" m:m;   
  7.             ss = s.length===1?"0" s:s;   
  8.   
  9.             var nowdate = h ":" m ":" s;   
  10.             var tx = (canvas.width-((P_radius*2 X_J)*4*8 7*xjg))/2,color = "";   
  11.             for(var i=0;i<nowdate.length;i ){   
  12.                 var n = nowdate.charAt(i)===":"?10:parseInt(nowdate.charAt(i)),   
  13.                     text = numData[n];   
  14.   
  15.                 var ty = (canvas.height-((P_radius yjg)*6))/2;   
  16.   
  17.                 switch(i){   
  18.                     case 0:color = "#4DCB74";break;   
  19.                     case 2:color = "#4062E0";break;   
  20.                     case 3:color = "#D65050";break;   
  21.                     case 5:color = "#4062E0";break;   
  22.                     case 6:color = "#797C17";break;   
  23.                 }   
  24.   
  25.                 for(var j=0;j<text.length;j ){   
  26.                     var tt = text.charAt(j);   
  27.                     if(tt==="/"){   
  28.                         ty =yjg;   
  29.                     }else{   
  30.                         var x = tx j%5*(P_radius*2 X_J),   
  31.                             y = ty,   
  32.                             pp = null,   
  33.                             usefullp = null;   
  34.                         particles.forEach(function(p){   
  35.                             if(p.visible&p.x===x&p.y===y){   
  36.                                 ppp = p;   
  37.                             }else if(!p.visible&usefullp===null){   
  38.                                 usefullp = p;   
  39.                             }   
  40.                         });   
  41.                         if(pp!==null&tt==="0"){   
  42.                             pp.isDrop();   
  43.                         }else if(pp===null&tt==="1"){   
  44.                             usefullp.reset(x , y , color);   
  45.                         }   
  46.                     }   
  47.                 }   
  48.                 tx =xjg 4*(P_radius*2 X_J);   
  49.             }   
  50.         }  

  原理也轻便,也是跟上边画背景差不离,遍历全体一点,然后依照当几天前子的数字转形成的字符串来剖断,当前点是还是不是应该有像素,如若有像素就再推断当前那几个点是还是不是早就有粒子对象在了,假诺已经有粒子对象在了,就径直跳出不管理,若无粒子对象在,就再粒子容器中找二个尚无被应用的粒子reset到那些岗位。还会有朝气蓬勃种状态,便是日前这些点是不应有有像素的,不过却有粒子,那就拿走那个粒子,让那么些粒子进行自由落体。

  时间设置也写好了,就足以写舞台更新的代码了:

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

  1. var timeCount_0 = 0,timeCount_1 = 0,particles = [];   
  2.         function initAnimate(){   
  3.             for(var i=0;i<200;i ){   
  4.                 var p = new Particle();   
  5.                 particles.push(p);   
  6.             }   
  7.   
  8.             timeCount_0 = new Date();   
  9.             timeCount_1 = new Date();   
  10.             drawBg();   
  11.             setTime(timeCount_0)   
  12.             animate();   
  13.         }   
  14.   
  15.         function animate(){   
  16.             ctx.clearRect(0,0,canvas.width,canvas.height);   
  17.             ctx.drawImage(bgcanvas,0,0);   
  18.   
  19.             var timeCount_2 = new Date();   
  20.   
  21.             if(timeCount_1-timeCount_0>=1000){   
  22.                 setTime(timeCount_1);   
  23.                 timeCount_0 = timeCount_1;   
  24.             }   
  25.   
  26.             particles.forEach(function(p){   
  27.                 if(p.visible){   
  28.                     p.update((timeCount_2-timeCount_1)/70);   
  29.                     p.paint();   
  30.                 }   
  31.             });   
  32.   
  33.             timeCount_1 = timeCount_2;   
  34.   
  35.             RAF(animate)   
  36.         }  

  在initAnimate举办动漫开首化,起先化相当于先实例化八百个粒子对象放置粒子容器中保存起来,再立异时间戳,缓存背景,设置当前时光,然后调用animate动漫循环主体开首动漫。

  animate中的逻辑也超轻巧了,获取时间戳,若是三个日子戳之间的年月差大于或等于1秒,就进展setTime。而再下边包车型客车正是对粒子容器里的具备可视化的粒子进行遍历循环重绘了。
下一场就做好啦:
澳门新萄京 4

个成效照旧有为数不菲得以优化之处的,因为时钟和分钟都以动的可比少的,所以能够把这五个缓存起来,当未有动作的时候就一向将缓存数据画上去就行了,这样就能够减去舞台每后生可畏帧的绘图API调用量,分明是能加强品质的。不过未来毕竟粒子相当少,两三百个粒子对象也就充足了,借使不去做优化,动画也还是能够很流利的周转的。所以楼主就偷个小懒啦。

  源码地址:

那篇文章主要介绍了用HTML5创建数字石英钟的学科,首要行使HTML第55中学的Canvas API,须要的恋人能够参见下...

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

效果

澳门新萄京 5

澳门新萄京 6

本文由澳门新萄京发布于澳门新萄京最大平台,转载请注明出处:澳门新萄京:小公式大野趣,用HTML5中的Canvas结合

上一篇:没有了 下一篇:没有了
猜你喜欢
热门排行
精彩图文