巅云智能建站平台搭建版(创业流派版)火爆上线,毕生受权!新增:文章智能收罗+全站真静态打包+城市分站+智能小法式+不法词过滤+H5自顺应+智能链词等功效功效概况
建站资讯News

详解利用HTML5 Canvas建立静态粒子网格动画

0
一佰互联网站扶植(www.taishanly.com) 宣布时辰:2020-04-20 08:56:18 阅读数: 93

比来看到一个粒子网格动画挺炫的,本身也就做了一个,当背景挺不错的。CSDN不能上传跨越2M的图片,以是就简略截了一个静态图片:

上面就起头说怎样完成这个结果吧:

起首固然是增加一个canvas了:

<canvas id="canvas"></canvas>

上面是款式:

<style>    #canvas{        position: absolute;        display: block;        left:0;        top:0;        background: #0f0f0f;        z-index: -1;     }</style>

上面canvas的z-index: -1的感化是能够或许放在一些元素的上面当作背景。

为了确保canvas能够或许布满全数阅读器,以是要将canvas的宽高设置成和阅读器一样:

function getSize(){    w = canvas.width = window.innerWidth;    h = canvas.height = window.innerHeight;}

上面w和h别离代表阅读器的宽高。

取得了阅读器的宽高,接上去便是在外面画粒子了,这里咱们须要提早界说一些粒子的参数:

var opt = {    particleAmount: 50,         //粒子个数    defaultSpeed: 1,            //粒子勾当速率    variantSpeed: 1,            //粒子勾当速率的变量    particleColor: "rgb(32,245,245)",       //粒子的色彩    lineColor:"rgb(32,245,245)",            //网格连线的色彩    defaultRadius: 2,           //粒子半径    variantRadius: 2,           //粒子半径的变量    minDistance: 200            //粒子之间连线的最小间隔};

上面的速率变量和半径变量都是为了保障粒子的巨细和速率不是如出一辙。

而后咱们再建立一个类用来初始化粒子,代码比拟长,我都加了正文:

function Partical(){    this.x = Math.random()*w;           //粒子的x轴坐标    this.y = Math.random()*h;           //粒子的y轴坐标    this.speed = opt.defaultSpeed + opt.variantSpeed*Math.random();     //粒子的勾当速率    this.directionAngle = Math.floor(Math.random()*360);                //粒子勾当的标的目的    this.color = opt.particleColor ;                                    //粒子的色彩    this.radius = opt.defaultRadius+Math.random()*opt.variantRadius;    //粒子的半径巨细    this.vector = {        x:this.speed * Math.cos(this.directionAngle),       //粒子在x轴的速率        y:this.speed * Math.sin(this.directionAngle)        //粒子在y轴的速率    }    this.update = function(){                   //粒子的更新函数        this.border();                           //判定粒子是不是到了边境        this.x += this.vector.x;                //粒子下临时刻在x轴的坐标        this.y += this.vector.y;                //粒子下临时刻在y轴的坐标    }    this.border = function(){               //判定粒子是都达到边境        if(this.x >= w || this.x<= 0){      //若是达到摆布边境,就让x轴的速率变为本来的正数            this.vector.x *= -1;        }        if(this.y >= h || this.y <= 0){     //若是达到高低边境,就让y轴的速率变为本来的正数            this.vector.y *= -1;        }        if(this.x > w){                     //上面是转变阅读器窗口巨细时的操纵,转变窗口巨细后有的粒子会被埋没,让他显现出来便可            this.x = w;        }        if(this.y > h){            this.y = h;        }        if(this.x < 0){            this.x = 0;        }        if(this.y < 0){            this.y = 0;        }    }    this.draw = function(){                 //绘制粒子的函数        ctx.beginPath();        ctx.arc(this.x, this.y, this.radius ,0 ,Math.PI * 2);        ctx.closePath();        ctx.fillStyle = this.color;        ctx.fill();    }}

1、每一个粒子的初始速率和角度是随机天生的,粒子的色彩经由过程相干的设置选项来肯定。

2、this.vector用来存储粒子的挪动标的目的:若是this.vector.x为1,则粒子向右勾当;若是是-1,则粒子向左挪动。一样,若是this.vector.y为负,则粒子向上挪动,若是为正,则粒子向下挪动。

this.update用来更新每一个粒子下一个地位的坐标。起首,停止边缘检测;若是粒子的挪动超越了canvas的尺寸,则将标的目的向量乘以-1发生反向的勾当标的目的。

3、窗口缩放能够会引发粒子超越边境,如斯一来边缘检测函数就捉拿不到了,以是就须要一系列的if语句来检测这类环境,将粒子的地位重置为今后canvas的边境。

4、最初一步,将这些点绘制到画布上。

粒子的类已写好了,上面就把他绘制出来:

function init(){   getSize();   for(let i = 0;i<opt.particleAmount; i++){        particle.push(new Partical());   }   loop();}

上面初始化了opt.particleAmount个粒子工具,初始化了工具可是并不绘制出来,上面是loop函数:

function loop(){    ctx.clearRect(0,0,w,h);    for(let i = 0;i<particle.length; i++){        particle[i].update();        particle[i].draw();    }    window.requestAnimationFrame(loop);}

loop()函数每履行一次,城市断根canvas上的内容,而后经由过程粒子工具的update()函数从头计较粒子的坐标,最初经由过程粒子工具的draw()函数来绘制粒子。上面是这个时辰的结果:

可是在阅读器窗口巨细转变今后有些粒子就会消逝不见,这个时辰须要增加一个事务来监听阅读器巨细是不是转变:

window.addEventListener("resize",function(){    winResize()},false);

而后须要来写winResize()函数,这里须要注重一下,阅读器转变的时辰触发resize事务的次数会出格频仍,略微挪动一下阅读器的边缘便是触发几十次resize事务,那末也就会从头计较几十次阅读器巨细,比拟耗损机能,这个大师能够或许测试一下,这里就间接说处理体例吧,实在咱们要的只是阅读器转变后的最初的巨细,至于中间究竟转变了几多次和咱们不干系,以是咱们能够或许在阅读器窗口转变的时辰延缓200毫秒后履行计较阅读器巨细的事务,若是在这时代一向触发resize事务,那就一向今后延缓200毫秒,听起来挺庞杂,实在代码很简略:

var particle = [], w,h;     //粒子数组,阅读器宽高var delay = 200,tid;        //延缓履行事务和setTimeout事务援用function winResize(){    clearTimeout(tid);    tid = setTimeout(function(){        getSize();          //获得阅读器宽高,在文章最上面有先容    },delay)}

如许一切的粒子动画都完成了,接上去就能够或许在粒子之间画线了,咱们上面界说的opt工具外面有一个minDistance变量,当两个粒子之间的连线小于这个值的时辰,咱们就给他们之间画上线。

那末若何计较两个粒子之间的间隔呢,大师能够或许回忆一下初中数学第一课,勾股定理,直角三角形两个直角边的平方和即是第三条变的平方,看上面:

咱们此刻晓得每一个粒子的x轴和y轴的坐标,那末咱们就能够或许计较出两个点之间的间隔了,写一个函数,传入两个点,以下:

function getDistance(point1,point2){        return Math.sqrt(Math.pow(point1.x-point2.x,2) + Math.pow(point1.y - point2.y ,2));    }

此刻咱们能够或许计较出两个点的间隔,那末咱们就计较出一切每一个粒子同其余一切粒子的间隔,来肯定它们之间是不是须要连线,固然若是一切粒子的色彩深度都如出一辙,那就有点丑了,以是咱们这里能够或许按照两个粒子之间的间隔来决议连线的通明度,两个粒子间隔越近,越不通明,间隔越远,越通明,跨越必然间隔就不显现了。

function linePoint(point,hub){    for(let i = 0;i<hub.length;i++){        let distance = getDistance(point,hub[i]);        let opacity = 1 -distance/opt.minDistance;        if(opacity > 0){            ctx.lineWidth = 0.5;            ctx.strokeStyle = "rgba("+line[0]+","+line[1]+","+line[2]+","+opacity+")";            ctx.beginPath();            ctx.moveTo(point.x,point.y);            ctx.lineTo(hub[i].x,hub[i].y);            ctx.closePath();            ctx.stroke();        }    }}

上面传入的两个参数别离是一个点和全数点的数组,let opacity = 1 -distance/opt.minDistance;用于判定连线之间的通明度同时也判定了间隔,间隔大于opt.minDistance时,opacity为负,上面判定时就过滤掉了,上面的色彩用到了正则抒发式,须要先剖析最上面opt工具里给出的色彩,而后再加上通明度,这段代码以下:

var line = opt.lineColor.match(/d+/g);

最初在loop()函数外面不时轮回计较间隔就能够或许了,在loop()中插手代码后以下:

function loop(){        ctx.clearRect(0,0,w,h);        for(let i = 0;i<particle.length; i++){            particle[i].update();            particle[i].draw();        }        for(let i = 0;i<particle.length; i++){   //增加的是这个轮回            linePoint(particle[i],particle)        }        window.requestAnimationFrame(loop);    }

须要指出的是:若是增加过量的点和/或过量的毗连间隔(毗连间隔会建立过量的线条),动画也会扛不住。当视口变窄时最好下降粒子的勾当速率:粒子的尺寸越小,在越发狭小空间内的挪动速率貌似会越快。

显现整段代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>canvas粒子动画</title>    <style>        #canvas{            position: absolute;            display: block;            left:0;            top:0;            background: #0f0f0f;            z-index: -1;        }    </style></head><body><canvas id="canvas"></canvas><script>    var canvas = document.getElementById("canvas");    var ctx = canvas.getContext("2d");    var opt = {        particleAmount: 50,     //粒子个数        defaultSpeed: 1,        //粒子勾当速率        variantSpeed: 1,        //粒子勾当速率的变量        particleColor: "rgb(32,245,245)",       //粒子的色彩        lineColor:"rgb(32,245,245)",            //网格连线的色彩        defaultRadius: 2,           //粒子半径        variantRadius: 2,           //粒子半径的变量        minDistance: 200            //粒子之间连线的最小间隔    };    var line = opt.lineColor.match(/d+/g);    console.log(line);    var particle = [], w,h;    var delay = 200,tid;    init();    window.addEventListener("resize",function(){        winResize()    },false);    function winResize(){        clearTimeout(tid);        tid = setTimeout(function(){            getSize();        },delay)    }    function init(){        getSize();        for(let i = 0;i<opt.particleAmount; i++){            particle.push(new Partical());        }        loop();    }    function loop(){        ctx.clearRect(0,0,w,h);        for(let i = 0;i<particle.length; i++){            particle[i].update();            particle[i].draw();        }        for(let i = 0;i<particle.length; i++){            linePoint(particle[i],particle)        }        window.requestAnimationFrame(loop);    }    function linePoint(point,hub){        for(let i = 0;i<hub.length;i++){            let distance = getDistance(point,hub[i]);            let opacity = 1 -distance/opt.minDistance;            if(opacity > 0){                ctx.lineWidth = 0.5;                ctx.strokeStyle = "rgba("+line[0]+","+line[1]+","+line[2]+","+opacity+")";                ctx.beginPath();                ctx.moveTo(point.x,point.y);                ctx.lineTo(hub[i].x,hub[i].y);                ctx.closePath();                ctx.stroke();            }        }    }    function getDistance(point1,point2){        return Math.sqrt(Math.pow(point1.x-point2.x,2) + Math.pow(point1.y - point2.y ,2));    }    function getSize(){        w = canvas.width = window.innerWidth;        h = canvas.height = window.innerHeight;    }    function Partical(){        this.x = Math.random()*w;           //粒子的x轴坐标        this.y = Math.random()*h;           //粒子的y轴坐标        this.speed = opt.defaultSpeed + opt.variantSpeed*Math.random();     //粒子的勾当速率        this.directionAngle = Math.floor(Math.random()*360);                //粒子勾当的标的目的        this.color = opt.particleColor ;                                    //粒子的色彩        this.radius = opt.defaultRadius+Math.random()*opt.variantRadius;    //粒子的半径巨细        this.vector = {            x:this.speed * Math.cos(this.directionAngle),       //粒子在x轴的速率            y:this.speed * Math.sin(this.directionAngle)        //粒子在y轴的速率        }        this.update = function(){                   //粒子的更新函数            this.border();                           //判定粒子是不是到了边境            this.x += this.vector.x;                //粒子下临时刻在x轴的坐标            this.y += this.vector.y;                //粒子下临时刻在y轴的坐标        }        this.border = function(){               //判定粒子是都达到边境            if(this.x >= w || this.x<= 0){      //若是达到摆布边境,就让x轴的速率变为本来的正数                this.vector.x *= -1;            }            if(this.y >= h || this.y <= 0){     //若是达到高低边境,就让y轴的速率变为本来的正数                this.vector.y *= -1;            }            if(this.x > w){                     //上面是转变阅读器窗口巨细时的操纵,转变窗口巨细后有的粒子会被埋没,让他显现出来便可                this.x = w;            }            if(this.y > h){                this.y = h;            }            if(this.x < 0){                this.x = 0;            }            if(this.y < 0){                this.y = 0;            }        }        this.draw = function(){                 //绘制粒子的函数            ctx.beginPath();            ctx.arc(this.x, this.y, this.radius ,0 ,Math.PI * 2);            ctx.closePath();            ctx.fillStyle = this.color;            ctx.fill();        }    }</script></body></html>

以上便是本文的全数内容,但愿对大师的进修有所赞助,也但愿大师多多撑持网页设想。

一佰互联是天下着名建站品牌办事商,咱们有九年、网站建造、网页设想、php开辟和域名注册及假造主机办事经历,供给的办事更是天下着名。最近几年来还整合团队上风自立开辟了可视化多用户”“3.0平台版,拖拽排版网站建造设想,轻松完成pc站、手机微网站、小法式、APP一体化全网营销网站扶植 ,已胜利的为天下上百家收集公司供给自助建站平台搭建办事。更多资讯:tags标签

上一篇:HTML5 Canvas玩转酷炫大波浪进度图结果实例(附demo)
下一篇: H5新属性audio音频和video视频的节制详解(保举)
[前往消息列表]

相干消息more

23
04月
tomcat假造主机_能源节点Java学院整

对Tomcat办事器,能够或许安排多个网站(多个web利用),这便是讲设置装备摆设多个假造主机,能够或许当作仿佛有多个主机,而每一个主机上有一个web利用。... >>概况

14
05月
影响医疗网站转化率的三大焦点身分_巅云建站

明天在网上看了一篇文章《谈谈病院的转化率》,讲了3点,一:关头词和创意,二:着陆页的阐发,三:进步客服的才能。 看了以后我感受这写的有些敷衍... >>概况

26
03月
收集危险办理:营业团队与宁静团队之间的空缺

简介:营业司理想要获得及时收集危险办理目标,但收集宁静团队只能托付手艺数据和阶段性报告。这中间的空缺须要获得弥补。几年前,收集宁静职员经常哀... >>概况

10
04月
巅云年度专题清点!2017年最受接待的电商设

巅云年度专题第二弹!这个专题里咱们为大师清算了2017年人气最高的电商设想文章,既有最罕见的Banner 设想套路,最新颖的电商设想趋向,也... >>概况

高端网站扶植

美工统筹SEO,为企业电子商务营销助力!

德律风:

023-85725751
建站

产物

域名注册 假造主机 云办事器 企业邮局
智能建站 APP打包 微站/小法式 创业平台
网站推行 媒体营销 智能收罗 AI机械人
400德律风 短信营销 店销机械人
私家定制 流派网站