的运营机制及爬坑指南,canvas学习笔记

时间:2019-10-06 23:57来源:美高梅游戏网站
canvas学习笔记:小公式大野趣 2014/03/20 · HTML5 · 1评论 ·HTML5 原稿出处: WAxes    近年想弄二个网页,把温馨学HTML5经过中做的有的DEMO放上去做集结,不过,假诺就唯有做个网页把全部

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

JavaScript 中 this 的运营机制及爬坑指南

2018/03/14 · JavaScript · this

原作出处: [Dr. Axel

JavaScript 中的 this 周到分析

2017/05/26 · JavaScript · this

初稿出处: Simon_ITer   

GitHub地址:

this的指向难点应有是让每叁个前端er都胃疼的主题材料,小编也长期以来,曾经遭遇乃至都是一顿乱猜。近年来在研读一些书籍如《你不知底的JavaScript》和《JavaScript语言非凡与编程实践》,让自身对this的难题峰回路转。故写下此篇小说,分享一下本人的经验。

H5 Crash 研究

2016/05/31 · HTML5 · Crash

初稿出处: 小胡子哥(@Barret托塔天王)   

咱俩精晓,支撑页面在 webview 上能够运维的前提是装有叁个神速並且稳固的 webview 容器,而容器的快捷牢固不止由容器提供方来保险,也亟需容器使用者遵守一些基本准绳,不然就有比十分的大希望现身页面 Crash 的气象,那么些轨道是何等?什么样的上层代码会唤起容器极度退出?这是本文须要演讲的源委。

换个思路清楚Javascript中的this

2017/07/27 · JavaScript · this

原来的作品出处: Leechikit   

在网络海人民广播广播台湾大学稿子都对 Javascript 中的 this 做了详实的牵线,但大约是介绍各样绑定情势或调用格局下 this 的指向,于是小编想有五个联合的思绪来越来越好通晓 this 指向,使大家更加好剖断,以下有一对内容不是常理,而是一种解题思路。

Rauschmayer]()   译文出处:[众成翻译

woolll]()   

图片 2

在 JavaScript 中,this 这几个特别的变量是相对相比较复杂的,因为 this 不独有用在面向对象情形中,在任何任哪个地方方也是可用的。 本篇博文中会解释 this 是怎样行事的以及使用中恐怕导致难题的地点,最后奉上最好施行。

的运营机制及爬坑指南,canvas学习笔记。为了更加好精晓 this,将 this 使用的场景分成三类:

  • 在函数内部 this 三个特别的,平常是包罗的参数。
  • 在函数外界(顶尖功用域中): 那指的是浏览器中的全局对象恐怕Node.js 中七个模块的输出。
  • 在传递给eval()的字符串中: eval() 或然猎取 this 当前值值,也许将其设置为大局对象,决计于 this 是一直调用依然直接调用。

大家来拜见各种门类。

隐式绑定

至于this,平日的话,什么人调用了主意,该措施的this就对准何人,如:

function foo(){ console.log(this.a) } var a = 3; var obj = { a: 2, foo: foo }; obj.foo(); // 输出2,因为是obj调用的foo,所以foo的this指向了obj,而obj.a = 2

1
2
3
4
5
6
7
8
9
10
11
12
function foo(){
    console.log(this.a)
}
 
var a = 3;
 
var obj = {
    a: 2,
    foo: foo
};
 
obj.foo(); // 输出2,因为是obj调用的foo,所以foo的this指向了obj,而obj.a = 2

倘诺存在数次调用,对象属性引用链只有上一层可能说最终一层在调用地方中起成效,如:

function foo() { console.log( this.a ) } var obj2 = { a: 42, foo: foo } var obj1 = { a: 2, obj2: obj2 } obj1.obj2.foo(); // 42

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function foo() {
    console.log( this.a )
}
 
var obj2 = {
    a: 42,
    foo: foo
}
 
var obj1 = {
    a: 2,
    obj2: obj2
}
 
obj1.obj2.foo(); // 42

H5 Crash 难题大约

下图是 H5 Crash 的大概流程图:

图片 3

鉴于前端不可能捕捉到页面 Crash 的景观和储藏室,可是 H5 页面上发出的一无可取会传送到 Java 和更底层的 Native 直到容器分外退出,在脱离的那一刻,容器会将饭店写入到日志中,当下一次开荒容器时(也说不定是定时报告)就能够报告那么些饭馆音讯。

从call方法初步

call 方法允许切换函数实践的上下文情形(context),即 this 绑定的靶子。

大部介绍 this 的稿子中都会把 call 方法放到最终介绍,但此文大家要把 call 方法放在第一个人介绍,并从 call 方法切入来切磋 this ,因为 call 函数是显式绑定 this 的针对性,大家来看看它怎么模拟达成(不思虑传入 nullundefined 和原始值):

Function.prototype.call = function(thisArg) { var context = thisArg; var arr = []; var result; context.fn = this; for (let i = 1, len = arguments.length; i < len; i++) { arr.push('arguments[' + i + ']'); } result = eval("context.fn(" + arr + ")"); delete context.fn; return result; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Function.prototype.call = function(thisArg) {
    var context = thisArg;
    var arr = [];
    var result;
 
    context.fn = this;
 
    for (let i = 1, len = arguments.length; i < len; i++) {
        arr.push('arguments[' + i + ']');
    }
 
    result = eval("context.fn(" + arr + ")");
 
    delete context.fn;
 
    return result;
}

从上述代码大家能够看来,把调用 call 方法的函数作为第三个参数对象的情势,此时一定于把第二个参数对象作为函数试行的上下文景况,而 this 是指向函数推行的上下文境遇的,由此 this 就本着了第贰个参数对象,达成了 call 方法切换函数实践上下文意况的功力。

this 在函数中

那是最常用的 this 使用格局,函数通过扮演三种不一样的剧中人物来表示 JavaScript 中的全部可调用结构体:

  • 平时性函数(this 在非严厉方式下为全局对象,在严苛格局下为undefined)
  • 构造函数(this 指向新创立的实例)
  • 措施(this 是指方法调用的收信人)

在函数中,this 日常被以为是叁个外加的,隐含的参数。

隐式错失

贰个最常见的this绑定难点便是被隐式绑定的函数会丢弃绑定对象,也正是说他回答用暗中认可绑定,进而把this绑定到全局对象大概undefined上,决意于是或不是是严酷形式。

function foo() { console.log( this.a ) } var obj1 = { a: 2, foo: foo } var bar = obj1.foo; // 函数别称! var a = "oops, global"; // a是全局对象的属性 bar(); // "oops, global"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function foo() {
    console.log( this.a )
}
 
var obj1 = {
    a: 2,
    foo: foo
}
 
var bar = obj1.foo; // 函数别名!
 
var a = "oops, global"; // a是全局对象的属性
 
bar(); // "oops, global"

固然bar是obj.foo的二个援引,不过事实上,它引用的是foo函数本人,由此此时的bar()其实是三个不带任何修饰的函数调用,由此使用了暗许绑定

一个更微妙、更常见并且更想不到的图景产生在传入回调函数时

function foo() { console.log( this.a ) } function doFoo( fn ){ // fn 其实援用的是 foo fn(); //

1
2
3
4
5
6
7
function foo() {
    console.log( this.a )
}
 
function doFoo( fn ){
    // fn 其实引用的是 foo
    fn(); //

参数传递其实就是一种隐式赋值,由此我们传入函数时也会被隐式赋值,所以结果和上一个例证同样,要是把函数字传送入语言内置的函数并非传播自个儿注明的函数(如setTimeout等),结果也是一样的

H5 Crash 原因初探

测量检验代码 库房地址:

git clone ; cd demo;

1
2
git clone https://github.com/barretlee/h5crash.git;
cd demo;

注意: 代码须求在 Webview 容器中测量检验,PC 浏览器下不会出现相当。

H5 Crash 的来由不太精通,不过从经验上决断和搜索,大致归类为以下二种:

1. 内部存款和储蓄器难题

  • 测验方法:使用闭包,不断加多内部存款和储蓄器量,看看扩展到哪些区间大小, webview 容器会出现万分
  • 测验地方:(微信、今日头条或然另外顾客端展开该页面包车型客车客商,能够点走入测验下,选择100M 内部存款和储蓄器,不出意外,你的顾客端会闪退。)

XHTML

<script> var Closure = function() { var _cache = []; var cache = 0; var add = function(size) { cache += size; size = size * 1024 * 1024; _cache.push(new Array(size).join('x')); refresh(); }; var refresh = function() { r.innerHTML = '内部存款和储蓄器消耗: ' + cache + 'M'; }; return { cache: cache + 'M', add: add, refresh: refresh } }; var closure = Closure(); </script> <button onclick="closure.add(1)">扩展1M 内部存储器消耗</button> <button onclick="closure.add(10)">增加10M 内部存款和储蓄器消耗</button> <button onclick="closure.add(20)">扩张20M 内部存款和储蓄器消耗</button> <button onclick="closure.add(50)">扩展50M 内部存款和储蓄器消耗</button> <button onclick="closure.add(100)">扩大 100M 内部存款和储蓄器消耗</button> <div id="r">内部存储器消耗:0 M</div>

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
<script>
var Closure = function() {
  var _cache = [];
  var cache = 0;
  var add = function(size) {
    cache += size;
    size = size * 1024 * 1024;
    _cache.push(new Array(size).join('x'));
    refresh();
  };
  var refresh = function() {
    r.innerHTML = '内存消耗: ' + cache + 'M';
  };
  return {
    cache: cache + 'M',
    add: add,
    refresh: refresh
  }
};
var closure = Closure();
</script>
 
<button onclick="closure.add(1)">增加 1M 内存消耗</button>
<button onclick="closure.add(10)">增加 10M 内存消耗</button>
<button onclick="closure.add(20)">增加 20M 内存消耗</button>
<button onclick="closure.add(50)">增加 50M 内存消耗</button>
<button onclick="closure.add(100)">增加 100M 内存消耗</button>
 
<div id="r">内存消耗:0 M</div>

存在的烦闷:这种测量检验存在比比较多的扰乱,举例设备等级次序、系统项目(iOS/Android)、和器材内存运行状态等。

2. Layers 数问题

Layers 数的获得相比较费心,Chrome Driver 未有提供该数据的接口,近日也未有相比较好的点子获得这么些数目。

  • 测量检验方法:通过分化的措施创制层,观望页面的 Crash 景况
  • 测量检验地方:

XHTML

<style>.transform { transform: translateZ(0); } .animation { width:100px; height:100px; background:red; position:relative; animation:move 5s infinite; } @keyframes move { from {left:0px;} to {left:200px;} } </style> <script> var Layer = function() { function getType() { return document.querySelector('input:checked').value; }; return { createOne: function(index) { var div = document.createElement('div'); div.appendChild(document.createTextNode(index)); switch(getType()) { case 'opacity': div.style.cssText = "opacity:" + (index / 1000); break; case 'transform': div.className = 'transform'; break; case 'animation': div.className = 'animation'; break; case 'zindex': div.style.cssText = "position:relative; z-index:" + index; break; } document.body.appendChild(div); }, create: function(num) { [].slice.call(document.querySelectorAll('div')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.createOne(num); } } } }; var layer = Layer(); </script> <strong>层类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 成立层</span></label></li> <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 成立层</span></label></li> <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 成立层</span></label></li> <li><label><input type="radio" name="type" value="zindex"> <span>通过相对定位分层</span></label></li> </ul> <button onclick="layer.create(1)">创立 1 个层</button> <button onclick="layer.create(10)">制造 13个层</button> <button onclick="layer.create(20)">创设 十八个层</button> <button onclick="layer.create(50)">创立 肆十九个层</button> <button onclick="layer.create(100)">成立 100 个层</button> <button onclick="layer.create(200)">成立 200 个层</button> <button onclick="layer.create(500)">创造 500 个层</button> <button onclick="layer.create(1000)">成立 一千个层</button> <button onclick="layer.create(两千)">成立 3000个层</button> <button onclick="layer.create(伍仟)">创制 五千个层</button> <button onclick="layer.create(一千0)">创设一千0 个层</button>

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
<style>.transform {
  transform: translateZ(0);
}
.animation {
  width:100px;
  height:100px;
  background:red;
  position:relative;
  animation:move 5s infinite;
}
 
@keyframes move {
  from {left:0px;}
  to {left:200px;}
}
</style>
<script>
var Layer = function() {
  function getType() {
    return document.querySelector('input:checked').value;
  };
  return {
    createOne: function(index) {
      var div = document.createElement('div');
      div.appendChild(document.createTextNode(index));
      switch(getType()) {
        case 'opacity':
          div.style.cssText = "opacity:" + (index / 1000);
          break;
        case  'transform':
          div.className = 'transform';
          break;
        case  'animation':
          div.className = 'animation';
          break;
        case  'zindex':
          div.style.cssText = "position:relative; z-index:" + index;
          break;
      }
      document.body.appendChild(div);
    },
    create: function(num) {
      [].slice.call(document.querySelectorAll('div')).forEach(function(item) {
        item.parentNode && item.parentNode.removeChild(item);
      });
      while(num--) {
        this.createOne(num);
      }
    }
  }
};
var layer = Layer();
</script>
 
<strong>层类型: </strong>
<ul>
  <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li>
  <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li>
  <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li>
  <li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li>
</ul>
 
<button onclick="layer.create(1)">创建 1 个层</button>
<button onclick="layer.create(10)">创建 10 个层</button>
<button onclick="layer.create(20)">创建 20 个层</button>
<button onclick="layer.create(50)">创建 50 个层</button>
<button onclick="layer.create(100)">创建 100 个层</button>
<button onclick="layer.create(200)">创建 200 个层</button>
<button onclick="layer.create(500)">创建 500 个层</button>
<button onclick="layer.create(1000)">创建 1000 个层</button>
<button onclick="layer.create(2000)">创建 2000 个层</button>
<button onclick="layer.create(5000)">创建 5000 个层</button>
<button onclick="layer.create(10000)">创建 10000 个层</button>
  • 实在,创设几个层,也是对内部存款和储蓄器的巨人消耗,页面 Crash 或许照旧因为内部存款和储蓄器消耗过大

3. 并发过多难题

  • 测量检验方法:尝试并发发出两种不一样的伸手(Fetch央求、XHGL450央浼、Script/CSS 能源乞请),观看页面 Crash 境况
  • 测量检验地方:

XHTML

<script> var Request = function() { function getType() { return document.querySelector('input:checked').value; }; function getResource() { var type = getType(); var resource = { fetch: '/', xhr: '/', script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js', css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css' }; return resource[type]; }; return { emitOne: function() { var url = getResource() + "?_t=" + (new Date * 1 + Math.random()); switch(getType()) { case 'fetch': return fetch('/'); case 'xhr': with(new XMLHttpRequest) { open('GET', url); send(); } return; case 'script': var s = document.createElement('script'); s.src = url; document.body.appendChild(s); return; case 'css': var s = document.createElement('link'); s.href = url; document.body.appendChild(s); } }, emit: function(num) { [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.emitOne(); } } } }; var request = Request(); </script> <strong>央浼类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送须要</span></label></li> <li><label><input type="radio" name="type" value="xhr"> <span>使用 XH昂Cora发送央求</span></label></li> <li><label><input type="radio" name="type" value="script"> <span>并发央求脚本财富</span></label></li> <li><label><input type="radio" name="type" value="css"> <span>并发央浼样式财富</span></label></li> </ul> <button onclick="request.emit(1)">并发 1 个诉求</button> <button onclick="request.emit(10)">并发 十二个必要</button> <button onclick="request.emit(20)">并发 18个需要</button> <button onclick="request.emit(50)">并发 肆拾叁个央求</button> <button onclick="request.emit(100)">并发 100 个诉求</button> <button onclick="request.emit(500)">并发 500 个乞求</button> <button onclick="request.emit(一千)">并发 一千 个诉求</button>

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
<script>
var Request = function() {
  function getType() {
    return document.querySelector('input:checked').value;
  };
  function getResource() {
    var type = getType();
    var resource = {
      fetch: '/',
      xhr: '/',
      script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js',
      css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css'
    };
    return resource[type];
  };
  return {
    emitOne: function() {
      var url = getResource() + "?_t=" + (new Date * 1 + Math.random());
      switch(getType()) {
        case 'fetch':
          return fetch('/');
        case 'xhr':
          with(new XMLHttpRequest) {
            open('GET', url);
            send();
          }
          return;
        case 'script':
          var s = document.createElement('script');
          s.src = url;
          document.body.appendChild(s);
          return;
        case 'css':
          var s = document.createElement('link');
          s.href = url;
          document.body.appendChild(s);
      }
    },
    emit: function(num) {
      [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) {
        item.parentNode && item.parentNode.removeChild(item);
      });
      while(num--) {
        this.emitOne();
      }
    }
  }
};
var request = Request();
</script>
 
<strong>请求类型: </strong>
<ul>
  <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li>
  <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li>
  <li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li>
  <li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li>
</ul>
 
<button onclick="request.emit(1)">并发 1 个请求</button>
<button onclick="request.emit(10)">并发 10 个请求</button>
<button onclick="request.emit(20)">并发 20 个请求</button>
<button onclick="request.emit(50)">并发 50 个请求</button>
<button onclick="request.emit(100)">并发 100 个请求</button>
<button onclick="request.emit(500)">并发 500 个请求</button>
<button onclick="request.emit(1000)">并发 1000 个请求</button>
  • 存在的忧愁:设备的类别、设备的 CPU 使用情况和网络情状等。

对象方法中的this

在模拟 call 方法的时候,我们利用了目的方法来改换 this 的针对性。调用对象中的方法时,会把指标作为艺术的上下文景况来调用。

既然 this 是指向实行函数的上下文碰着的,那大家先来研讨一下调用函数时的实行上下文意况。

上面笔者门来拜谒调用对象方法时执行上下文是怎样的:

var foo = { x : 1, getX: function(){ console.log(this.x); } } foo.getX();

1
2
3
4
5
6
7
var foo = {
    x : 1,
    getX: function(){
        console.log(this.x);
    }
}
foo.getX();

图片 4

从上海教室中,大家可以看看getX艺术的调用者的上下文是foo,因此getX方法中的 this 指向调用者上下文foo,转换成 call 方法为foo.getX.call(foo)

上边大家把别的函数的调用方式都按调用对象方法的思路来改换。

编辑:美高梅游戏网站 本文来源:的运营机制及爬坑指南,canvas学习笔记

关键词: