用 Canvas 编织炫耀星空图

2016/05/14 · CSS ·
Canvas,
画布

初稿出处: Cyandev   

先来探视最后的效应:

永利开户送38元体验金 1

GitHub项目: CyandevToys /
ParticleWeb
是或不是还蛮酷的呢?本文大家就来一点一点解析怎么落到实处它!


初稿出处: WAxes   

分析

先是大家看看那么些效果具体有那多少个要点。首先,这么炫彩的效率一定是要用到
Canvas
了,各样星星可以看作为一个粒子,由此,整个功能其实正是粒子系统了。此外,我们得以窥见每种粒子之间是互相连接的,只可是离的近的粒子之间的连线极粗且折射率异常的低,而离的远的则相反。

近来想弄一个网页,把温馨学HTML5进度中做的风流洒脱对DEMO放上去做集合,但是,要是就可是做个网页把具有DEMO三个叁个排列又感到太掉价了。就想,既然学了canvas,那就来折腾下浏览器,做个小小开场动漫吧。

开始 Coding

开场动漫的功用,想了一会,决定用粒子,因为以为粒子相比较有趣。还记得以前笔者写的率先篇本领博文,正是讲文字图片粒子化的:文字图片粒子化 ,
此时就偏偏做的是直线运动,顺便加了好几3D意义。运动公式很简短。所以就想那一个开场动漫就做的更充沛一些呢。

HTML 部分

那部分小编就大致放了三个 “ 标签,设置样式使其填写全屏。

<canvas height=”620″ width=”1360″ id=”canvas” style=”position:
absolute; height: 100%;”/>

1
<canvas height="620" width="1360" id="canvas" style="position: absolute; height: 100%;"/>

然后为了让抱有因素未有间距和内补,笔者还加了一条全局样式:

* { margin: 0; padding: 0; }

1
2
3
4
    * {
      margin: 0;
      padding: 0;
    }

先上DEMO:

JavaScript 部分

上面大家来写大旨的代码。首先大家要拿到那么些 canvas 并收获绘制上下文:

var canvasEl = document.getElementById(‘canvas’); var ctx =
canvasEl.getContext(‘2d’); var mousePos = [0, 0];

1
2
3
var canvasEl = document.getElementById(‘canvas’);
var ctx = canvasEl.getContext(‘2d’);
var mousePos = [0, 0];

进而我们评释七个变量,分别用于存款和储蓄“星星”和边:

var nodes = []; var edges = [];

1
2
var nodes = [];
var edges = [];

下一步,我们做些绸缪干活,正是让画布在窗口大小爆发变化时再一次绘制,何况调动本身分辨率:

window.onresize = function () { canvasEl.width =
document.body.clientWidth; canvasEl.height = canvasEl.clientHeight; if
(nodes.length == 0) { constructNodes(); } render(); };
window.onresize(); // trigger the event manually.

1
2
3
4
5
6
7
8
9
10
11
12
window.onresize = function () {
    canvasEl.width = document.body.clientWidth;
    canvasEl.height = canvasEl.clientHeight;
 
    if (nodes.length == 0) {
      constructNodes();
    }
 
    render();
};
 
window.onresize(); // trigger the event manually.

笔者们在第一遍改良尺寸后创设了颇负节点,这里就要用到下三个函数(constructNodes)了

本条函数中大家随意创造多少个点,大家用字典对象的主意存款和储蓄那几个点的顺序新闻:

function constructNodes() { for (var i = 0; i < 100; i++) { var node
= { drivenByMouse: i == 0, x: Math.random() * canvasEl.width, y:
Math.random() * canvasEl.height, vx: Math.random() * 1 – 0.5, vy:
Math.random() * 1 – 0.5, radius: Math.random() > 0.9 ? 3 +
Math.random() * 3 : 1 + Math.random() * 3 }; nodes.push(node); }
nodes.forEach(function (e) { nodes.forEach(function (e2) { if (e == e2)
{ return; } var edge = { from: e, to: e2 } addEdge(edge); }); }); }

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
function constructNodes() {
    for (var i = 0; i < 100; i++) {
      var node = {
        drivenByMouse: i == 0,
        x: Math.random() * canvasEl.width,
        y: Math.random() * canvasEl.height,
        vx: Math.random() * 1 – 0.5,
        vy: Math.random() * 1 – 0.5,
        radius: Math.random() > 0.9 ? 3 + Math.random() * 3 : 1 + Math.random() * 3
      };
 
      nodes.push(node);
    }
 
    nodes.forEach(function (e) {
      nodes.forEach(function (e2) {
        if (e == e2) {
          return;
        }
 
        var edge = {
          from: e,
          to: e2
        }
 
        addEdge(edge);
      });
    });
  }

为了完结前面八个更炫耀的成效,小编给第二个点加了叁个 drivenByMouse
属性,这几个点的岗位不会被粒子系统管理,也不会绘制出来,然则它会与其他点连线,那样就达成了鼠标跟随的意义了。

此地微微解释一下 radius
属性的取值,笔者梦想让绝超过半数点都以小半径的,而极个别的点半径非常的大,所以自个儿这里用了少数小
tricky,就是用可能率调控点的半径取值,不断调解这些概率阈值就能够博取期望的半径随机分布。

点都营造达成了,将在塑造点与点期间的连线了,大家用到再也遍历,把八个点捆绑成黄金时代组,放到
edges 数组中。注意这里小编用了别的七个函数来变成那件事,而未有一贯用
edges.push() ,为什么?

假定大家事前接连了
A、B两点,也等于外面循环是A,内侧循环是B,那么在下三回巡回中,外侧为B,内侧为A,是否也会创制一条边呢?而其实,那四个边除了方向分歧等以外是全然相近的,那统统未有供给何况占用财富。因而大家在
addEdge 函数中开展贰个论断:

function addEdge(edge) { var ignore = false; edges.forEach(function (e)
{ if (e.from == edge.from & e.to == edge.to) { ignore = true; } if (e.to
== edge.from & e.from == edge.to) { ignore = true; } }); if (!ignore) {
edges.push(edge); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function addEdge(edge) {
    var ignore = false;
 
    edges.forEach(function (e) {
      if (e.from == edge.from & e.to == edge.to) {
        ignore = true;
      }
 
      if (e.to == edge.from & e.from == edge.to) {
        ignore = true;
      }
    });
 
    if (!ignore) {
      edges.push(edge);
    }
  }

至今,我们的预备工作就结束了,下边大家要让点动起来:

function step() { nodes.forEach(function (e) { if (e.drivenByMouse) {
return; } e.x += e.vx; e.y += e.vy; function clamp(min, max, value) { if
(value > max) { return max; } else if (value < min) { return min;
} else { return value; } } if (e.x <= 0 || e.x >= canvasEl.width)
{ e.vx *= -1; e.x = clamp(0, canvasEl.width, e.x) } if (e.y <= 0 ||
e.y >= canvasEl.height) { e.vy *= -1; e.y = clamp(0,
canvasEl.height, e.y) } }); adjustNodeDrivenByMouse(); render();
window.requestAnimationFrame(step); } function adjustNodeDrivenByMouse()
{ nodes[0].x += (mousePos[0] – nodes[0].x) / easingFactor;
nodes[0].y += (mousePos[1] – nodes[0].y) / easingFactor; }

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
function step() {
    nodes.forEach(function (e) {
      if (e.drivenByMouse) {
        return;
      }
 
      e.x += e.vx;
      e.y += e.vy;
 
      function clamp(min, max, value) {
        if (value > max) {
          return max;
        } else if (value < min) {
          return min;
        } else {
          return value;
        }
      }
 
      if (e.x <= 0 || e.x >= canvasEl.width) {
        e.vx *= -1;
        e.x = clamp(0, canvasEl.width, e.x)
      }
 
      if (e.y <= 0 || e.y >= canvasEl.height) {
        e.vy *= -1;
        e.y = clamp(0, canvasEl.height, e.y)
      }
    });
 
    adjustNodeDrivenByMouse();
    render();
    window.requestAnimationFrame(step);
  }
 
  function adjustNodeDrivenByMouse() {
    nodes[0].x += (mousePos[0] – nodes[0].x) / easingFactor;
    nodes[0].y += (mousePos[1] – nodes[0].y) / easingFactor;
  }

见到那般第一次全国代表大会段代码不要惊慌,其实做的专门的学问很简短。那是粒子系统的主干,正是遍历粒子,并且更新其情景。更新的公式就是

v = v + a s = s + v

1
2
v = v + a
s = s + v

a是加快度,v是速度,s是位移。由于大家那边不关乎加快度,所以就不写了。然后大家供给作七个边缘的碰撞检测,不然大家的“星星”都自由自在地一点点飞~走~了~。边缘碰撞后的管理格局正是让速度矢量反转,那样粒子就能“掉头”回来。

还记得大家须求做的鼠标跟随吗?也在这里管理,大家让第多少个点之处一点一点运动到鼠标的地点,上面那一个公式很有趣,能够轻巧实现缓动:

x = x + (t – x) / factor

1
x = x + (t – x) / factor

当中 factor 是缓动机原因子,t 是终极地方,x
是眼下位置。至于那个公式的解释还会有个相互大神 Bret 维克多在他的发言中提到过,摄像做的相当好,有条(ti)件(zi)大家自然要看看:
Bret Victor – Stop Drawing Dead
Fish

好了,回到主旨。大家在上头的函数中拍卖完了生机勃勃帧中的数据,大家要让漫天粒子系统三回九转地运行起来就需求七个timer了,不过那一个不提倡大家利用
setInterval,而是尽量接纳
requestAnimationFrame,它能承保你的帧率锁定在

余下的正是绘制啦:

function render() { ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0,
canvasEl.width, canvasEl.height); edges.forEach(function (e) { var l =
lengthOfEdge(e); var threshold = canvasEl.width / 8; if (l >
threshold) { return; } ctx.strokeStyle = edgeColor; ctx.lineWidth = (1.0

  • l / threshold) * 2.5; ctx.globalAlpha = 1.0 – l / threshold;
    ctx.beginPath(); ctx.moveTo(e.from.x, e.from.y); ctx.lineTo(e.to.x,
    e.to.y); ctx.stroke(); }); ctx.globalAlpha = 1.0; nodes.forEach(function
    (e) { if (e.drivenByMouse) { return; } ctx.fillStyle = nodeColor;
    ctx.beginPath(); ctx.arc(e.x, e.y, e.radius, 0, 2 * Math.PI);
    ctx.fill(); }); }
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
function render() {
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvasEl.width, canvasEl.height);
 
    edges.forEach(function (e) {
      var l = lengthOfEdge(e);
      var threshold = canvasEl.width / 8;
 
      if (l > threshold) {
        return;
      }
 
      ctx.strokeStyle = edgeColor;
      ctx.lineWidth = (1.0 – l / threshold) * 2.5;
      ctx.globalAlpha = 1.0 – l / threshold;
      ctx.beginPath();
      ctx.moveTo(e.from.x, e.from.y);
      ctx.lineTo(e.to.x, e.to.y);
      ctx.stroke();
    });
    ctx.globalAlpha = 1.0;
 
    nodes.forEach(function (e) {
      if (e.drivenByMouse) {
        return;
      }
 
      ctx.fillStyle = nodeColor;
      ctx.beginPath();
      ctx.arc(e.x, e.y, e.radius, 0, 2 * Math.PI);
      ctx.fill();
    });
  }

常规的 Canvas 绘图操作,注意 beginPath
应当要调用,不然你的线就满门穿在联合签名了…
要求表明的是,在绘制边的时候,大家先要总计两点离开,然后依据二个阈值来判定是还是不是要绘制那条边,那样我们技巧促成间距远的点时期连线不可以预知的效果与利益。

到这里,我们的大器晚成体职能就完了了。假如不知道大家也足以去小编文章早先放的
repo 离去看完整的源码。Have fun!!

2 赞 4 收藏
评论

永利开户送38元体验金 2

意义是不是比直线的移位更是振作激昂呢?并且也的确很简单,别忘了那篇博文的标题,小小滴公式,大大滴野趣。要做出如此的法力,用的就独自是我们初级中学。。也许高级中学时候的物理知识,增加速度移动,减速运动的公式啦。所以实乃小小滴公式。楼主很兴奋折腾一些炫目的事物,即使大概平日做事上用不上,不过,那野趣确实很令人着迷啊。何况,做下那一个也能够拉长一下编制程序的思维本事哈。

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

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

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;
            }
        },

粒子总共有三种状态,风姿浪漫种是自由落体,生龙活虎种就是非常受吸力。自由落体就隐蔽了。说吸力早前先贴出粒子的性质:

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是粒子和目标地之间连线的加快度,所以,大家因此粒子的任务和指标地的职位,通过轻便的三角形函数,就足以把粒子的品位加速度和垂直加速度求出来了,就这段

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

1
2
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;

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

永利开户送38元体验金,之所以要乘于0.97是为着模仿能量消耗,粒子才会减慢。time是每风流罗曼蒂克帧的小时差

总结出速度后就立异粒子地方就能够了。

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,进而减少粒子数量。

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("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);
                }
            }
        }

经过巡回获取到粒子的岗位xy值后,把地点赋给粒子,成为粒子的指标地。然后动漫伊始,就能够做出文字图片粒子化的职能了。

上边贴出动漫完毕的js代码。若是对其余代码也许有意思味的,可以直接看调控台哈,没压缩的。

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卡塔尔(英语:State of Qatar);
this.paint(卡塔尔国; } } var animate = function(卡塔尔{ this.state = “before” } var
ap = animate.prototype; ap.init = function(卡塔尔(英语:State of Qatar){ 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
draw图标(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&&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
评论

相关文章