做个小小的开场动画吧。

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

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

原文出处: WAxes   

最近想弄一个网页,把自己学HTML5过程中做的部分DEMO放上去做集合,但是,如果就仅仅做个网页把所有DEMO一个一个排列又觉得太难看了。就想,既然学了canvas,那就来折腾下浏览器,做个小小的开场动画吧。

开场动画的效果,想了一会,决定用粒子,因为觉得粒子比较好玩。还记得以前我写的第一篇技术博文,就是讲文字图片粒子化的:文字图片粒子化 ,
那时就仅仅做的是直线运动,顺便加了一点3D效果。运动公式很简单。所以就想这个开场动画就做的更动感一些吧。

先上DEMO:http://2.axescanvas.sinaapp.com/demoHome/index.html

效果是不是比直线的运动更加动感呢?而且也确实很简单,别忘了这篇博文的题目,小小滴公式,大大滴乐趣。要做出这样的效果,用的就仅仅是我们初中。。或者高中时候的物理知识,加速运动,减速运动的公式啦。所以确实是小小滴公式。楼主很喜欢折腾一些酷炫的东西,虽然可能平时工作上用不上,但是,这乐趣确实很让人着迷啊。而且,做下这些也可以加强一下编程的思维能力哈。

废话不多说,进入主题啦。就简单的解释一下原理吧~~~

粒子运动的核心代码就这么一点:

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注