详细说明使用HTML5画布创建动态粒子网格动画
我最近看到一个网格动画的一个粒子,和我做了一个,当背景是很good.csdn不能上传超过2M,所以它只是把静态图片:下面将开始说明如何实现这种效果。
当然,首先要添加一个画布:
以下是风格:
#帆布{
位置:绝对;
显示块;
左:0;
顶部:0;
背景:# 0f0f0f;
Z指数:1;
}
Z的功能:1以上的帆布可以放置一些元素为背景。
为了确保画布中充满了浏览器,有必要将画布设置为浏览器。
功能GetSize(){
W = canvas.width = window.innerwidth;
H = = window.innerheight canvas.height;
}
上面的w和h代表浏览器的宽高度。
为了获得浏览器的宽度,下一步是在其中绘制粒子。这里我们需要预先定义一些粒子的参数:
var
50 / / particleamount:,粒子数
1 / / defaultspeed:,粒子速度
1 / / variantspeed:,粒子速度变
particlecolor:RGB(32245245), / /粒子的颜色
LineColor:RGB(32245245),并网/颜色
2 / / defaultradius:,粒子半径
VariantRadius:2 / /粒子半径的变
200 mindistance之间的最小距离: / /颗粒附着
};
上面的速度和半径变量都是为了确保粒子的大小和速度不完全相同。
然后我们创建一个初始化粒子的类,代码很长,我给它添加一个注释。
函数粒子(){
这个X = Math.random(*宽); / / X轴的颗粒
这个y = Math.random(* H); / / Y轴颗粒
this.speed = opt.defaultspeed +(选择。variantspeed *数学。随机); / /粒子速度
this.directionangle = math.floor(数学。随机)(×360); / /粒子运动方向
this.color = opt.particlecolor; / /粒子的颜色
this.radius =选择。defaultradius + Math.random(*选择。variantradius); / /粒子半径
this.vector = { {
X:this.speed * Math.cos(这个方向角),X / /粒子在轴速度
Y:this.speed * Math.sin(这个方向角)在轴转速/ Y粒子
}
(this.update =功能){ / /粒子更新功能
(这个边界);以确定粒子是否到边界。
在x轴下一次。
在y轴下一次。
}
(this.border =功能){ / /粒子到达边界的判断
如果(这个X W,X <= | | > = 0){ / /如果达到周围边框,让X轴速度为原来的负
这个向量= x = 1;
}
如果(这。Y H,Y | | < = > = 0){ / /如果它达到的上限和下限,让Y轴速度为原来的负
这个向量= y = 1;
}
如果(此)在操作时间以下更改浏览器窗口,在隐藏一些粒子后更改窗口大小,以便显示
这个;
}
如果(这个)h
这个;
}
如果(此x<0){
这个,x=0;
}
如果(这个y<0){
这个,y=0;
}
}
(this.draw =功能){ / /绘图功能粒子
Ctx.beginPath();
Ctx.arc(这个X,Y,this.radius本。,0,math.pi×2);
Ctx.closePath();
ctx.fillstyle = this.color;
Ctx.fill();
}
}
1。每个粒子的初始速度和角度是随机生成的,粒子的颜色由相关的设置选项决定。
2、this.vector是用来存储一个粒子的运动方向:如果这个向量,X是1,粒子移动到右;如果是1,粒子移动到左侧,以同样的方式,如果这个向量,y是负的,粒子向上运动,如果它是积极的,向下移动的粒子。
this.update是用来更新每个粒子的下一个位置的坐标。首先进行边缘检测;如果粒子超越画布的大小、方向向量乘以1产生的运动方向相反。
3,窗口缩放会使粒子超出边界,从而无法捕获边缘检测功能。因此,需要一系列if语句来检测这种情况,并将粒子的位置重置为当前画布的边界。
4,最后一步是在画布上画出这些点。
粒子的种类已经写了,然后他把他拉出来:
函数init(){
GetSize();
为了(让我= 0;i < opt.particleamount;i++){
Particle.push(新粒子());
}
循环();
}
它初始化opt.particleamount粒子对象,初始化对象但不画它,以下是循环功能:
函数循环(){
ctx.clearrect(0,0,W,H);
为了(让我= 0;i < particle.length;i++){
粒子{ } }更新();
粒子{ };
}
window.requestanimationframe(环);
}
每次执行循环()函数,它清除画布上的内容。然后通过粒子对象的更新()函数计算粒子的坐标,最后通过粒子对象的绘制()函数绘制粒子:
但是当浏览器窗口的大小发生变化时,一些粒子就会消失。这一次,我们需要添加一个事件来监视浏览器大小是否改变。
Window.addEventListener(调整
WinResize()
},假);
然后你需要写(winresize)功能,需要注意的是,当浏览器改变触发数量调整大小事件特别频繁,略微移动浏览器的边缘是触发事件的几十个大小,所以也将重新计算的时候,浏览器会消耗更多的性能,数十本大小,你可以这里,只是说它的解决方案,其实我们要的只是尺寸上浏览器后的变化,中端改变了很多次,我们没关系,我们可以计算出浏览器的大小事件延迟200毫秒,当浏览器窗口的改变,如果在这期间已经触发了resize事件,它被延迟200毫秒,这听起来很复杂,其实很简单的代码:
var粒子{ },W,h,粒子数组,浏览器的宽度和高度
变量延迟= 200,tid; / /暂停事件和setTimeout事件参考
功能winresize(){
ClearTimeout(TID);
TID = setTimeout(){()函数(
(GetSize); / /得到的宽度和高度进行了浏览器,文章的上方
},延迟)
}
所以所有的粒子动画都完成了,然后我们可以画粒子之间的直线。选择对象定义的上面都有一个mindistance变量。当两个粒子之间的连接小于这个值时,我们将在它们之间画线。
那么如何计算这两个粒子之间的距离,我们可以回忆起初中数学课,勾股定理,直角三角形两直角边和等于第三的正方形,见下文:
我们现在知道x轴和每个粒子的y轴的坐标,所以我们可以计算两点之间的距离,写一个函数,并介绍如下两点。
功能getdistance(点、2){
返回Math.sqrt(Math.pow(1. x-point2。x 2)+ math.pow(1. Y 2。Y,2));
}
现在我们可以计算两点之间的距离,那么我们可以计算所有粒子与其他粒子的距离,确定是否需要连接它们,当然,如果所有的粒子的颜色深度是一模一样的,丑陋的,所以在这里我们可以根据的两粒子的距离更近,更透明,更遥远,更透明的透明的两粒子之间的关系决定的,超过一定的距离,不显示。
道路廊道的功能(点、中心){
为了(让我= 0;i < hub.length;i++){
让距离= getdistance(点、枢纽{我});
让不透明度1距离/ opt.mindistance;
如果(不透明度> 0){
ctx.linewidth = 0.5;
ctx.strokestyle =RGBA(+线{ 0 } +
Ctx.beginPath();
Ctx.moveTo(点。X,Y点。);
Ctx.lineTo(轮毂{ } { }。X,枢纽。Y);
Ctx.closePath();
Ctx.stroke();
}
}
}
上面的两个参数是通过一组点和点让,不透明度1距离/ opt.mindistance;用来确定透明度和距离的关系,距离超过opt.mindistance,透明度是负的,判断是过滤掉,上面的颜色使用正则表达式,需要解析以上选择了颜色的对象,然后添加透明度,这个代码如下:
VaR线= opt.linecolor.match( / D / G);
最后,在循环()函数中,我们可以不断地计算函数中的距离。在循环()中添加代码之后,如下所示:
函数循环(){
ctx.clearrect(0,0,W,H);
为了(让我= 0;i < particle.length;i++){
粒子{ } }更新();
粒子{ };
}
为了(让我= 0;i < particle.length;i++){ / /添加循环
道路廊道(粒子{我},粒子)
}
window.requestanimationframe(环);
}
需要指出的是,如果你添加太多的点和/或太多的连接距离(连接距离会产生太多的线),动画将不能携带它。当视口缩小的时候最好减少粒子的粒径和速度的速度在日益狭小的空间内部看起来更迅速。
显示整个代码:
帆布粒子动画
#帆布{
位置:绝对;
显示块;
左:0;
顶部:0;
背景:# 0f0f0f;
Z指数:1;
}
VaR的画布document.getelementbyid(画布);
VaR CTX = canvas.getcontext(2D);
var
50 / / particleamount:,粒子数
1 / / defaultspeed:,粒子速度
1 / / variantspeed:,粒子速度变
particlecolor:RGB(32245245), / /粒子的颜色
LineColor:RGB(32245245),并网/颜色
2 / / defaultradius:,粒子半径
VariantRadius:2 / /粒子半径的变
200 mindistance之间的最小距离: / /颗粒附着
};
VaR线= opt.linecolor.match( / D / G);
console.log(线);
var粒子= {,},w,h;
变量延迟= 200,tid;
init();
Window.addEventListener(调整
WinResize()
},假);
功能winresize(){
ClearTimeout(TID);
TID = setTimeout(){()函数(
GetSize();
},延迟)
}
函数init(){
GetSize();
为了(让我= 0;i < opt.particleamount;i++){
Particle.push(新粒子());
}
循环();
}
函数循环(){
ctx.clearrect(0,0,W,H);
为了(让我= 0;i < particle.length;i++){
粒子{ } }更新();
粒子{ };
}
为了(让我= 0;i < particle.length;i++){
道路廊道(粒子{我},粒子)
}
window.requestanimationframe(环);
}
道路廊道的功能(点、中心){
为了(让我= 0;i < hub.length;i++){
让距离= getdistance(点、枢纽{我});
让不透明度1距离/ opt.mindistance;
如果(不透明度> 0){
ctx.linewidth = 0.5;
ctx.strokestyle =RGBA(+线{ 0 } +
Ctx.beginPath();
Ctx.moveTo(点。X,Y点。);
Ctx.lineTo(轮毂{ } { }。X,枢纽。Y);
Ctx.closePath();
Ctx.stroke();
}
}
}
功能getdistance(点、2){
返回Math.sqrt(Math.pow(1. x-point2。x 2)+ math.pow(1. Y 2。Y,2));
}
功能GetSize(){
W = canvas.width = window.innerwidth;
H = = window.innerheight canvas.height;
}
函数粒子(){
这个X = Math.random(*宽); / / X轴的颗粒
这个y = Math.random(* H); / / Y轴颗粒
this.speed = opt.defaultspeed +(选择。variantspeed *数学。随机); / /粒子速度
this.directionangle = math.floor(数学。随机)(×360); / /粒子运动方向
this.color = opt.particlecolor; / /粒子的颜色
this.radius =选择。defaultradius + Math.random(*选择。variantradius); / /粒子半径
this.vector = { {
X:this.speed * Math.cos(这个方向角),X / /粒子在轴速度
Y:this.speed * Math.sin(这个方向角)在轴转速/ Y粒子
}
(this.update =功能){ / /粒子更新功能
(这个边界);以确定粒子是否到边界。
在x轴下一次。
在y轴下一次。
}
(this.border =功能){ / /粒子到达边界的判断
如果(这个X W,X <= | | > = 0){ / /如果达到周围边框,让X轴速度为原来的负
这个向量= x = 1;
}
如果(这。Y H,Y | | < = > = 0){ / /如果它达到的上限和下限,让Y轴速度为原来的负
这个向量= y = 1;
}
如果(此)在操作时间以下更改浏览器窗口,在隐藏一些粒子后更改窗口大小,以便显示
这个;
}
如果(这个)h
这个;
}
如果(此x<0){
这个,x=0;
}
如果(这个y<0){
这个,y=0;
}
}
(this.draw =功能){ / /绘图功能粒子
Ctx.beginPath();
Ctx.arc(这个X,Y,this.radius本。,0,math.pi×2);
Ctx.closePath();
ctx.fillstyle = this.color;
Ctx.fill();
}
}
以上是本文的全部内容,希望能对您有所帮助,希望大家多多支持。