详解应用HTML5 Canvas建立动态性颗粒网格动漫

日期:2021-02-24 类型:科技新闻 

关键词:h5小游戏,h5如何制作,免费h5在线制作,h5页面在线制作,测一测h5

近期看到1个颗粒网格动漫挺炫的,自身也就做了1个,当情况挺非常好的。CSDN不可以提交超出2M的照片,因此就简易截了1个静态数据照片:

下面就刚开始说如何完成这个实际效果吧:

最先自然是加上1个canvas了:

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

下面是款式:

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

上面canvas的z-index: ⑴的功效是能够放在1些元素的下面作为情况。

以便保证canvas可以填满全部访问器,因此要将canvas的宽高设定成和访问器1样:

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

上面w和h各自意味着访问器的宽高。

得到了访问器的宽高,接下来便是在里边画颗粒了,这里大家必须提早界定1些颗粒的主要参数:

var opt = {
    particleAmount: 50,         //颗粒个数
    defaultSpeed: 1,            //颗粒健身运动速率
    variantSpeed: 1,            //颗粒健身运动速率的自变量
    particleColor: "rgb(32,245,245)",       //颗粒的色调
    lineColor:"rgb(32,245,245)",            //网格连线的色调
    defaultRadius: 2,           //颗粒半径
    variantRadius: 2,           //颗粒半径的自变量
    minDistance: 200            //颗粒之间连线的最少间距
};

上面的速率自变量和半径自变量全是以便确保颗粒的尺寸和速率并不是1模1样。

随后大家再建立1个类用来原始化颗粒,编码较为长,我都加了注解:

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;                //颗粒下1時刻在x轴的座标
        this.y += this.vector.y;                //颗粒下1時刻在y轴的座标
    }
    this.border = function(){               //分辨颗粒是都抵达界限
        if(this.x >= w || this.x<= 0){      //假如抵达上下界限,就让x轴的速率变成原先的负数
            this.vector.x *= ⑴;
        }
        if(this.y >= h || this.y <= 0){     //假如抵达左右界限,就让y轴的速率变成原先的负数
            this.vector.y *= ⑴;
        }
        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,则颗粒向右健身运动;假如是⑴,则颗粒向左挪动。一样,假如this.vector.y为负,则颗粒向上挪动,假如为正,则颗粒向下挪动。

this.update用来升级每一个颗粒下1个部位的座标。最先,开展边沿检验;假如颗粒的挪动超过了canvas的规格,则将方位空间向量乘以⑴造成反方向的健身运动方位。

3、对话框放缩将会会引发颗粒超过界限,这般1来边沿检验涵数就捕获不到了,因此就必须1系列的if句子来检验这类状况,将颗粒的部位重设为当今canvas的界限。

4、最终1步,将这些点绘图到画布上。

颗粒的类早已写好了,下面就把他绘图出来:

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()涵数每实行1次,都会消除canvas上的內容,随后根据颗粒目标的update()涵数再次测算颗粒的座标,最终根据颗粒目标的draw()涵数来绘图颗粒。下面是这个情况下的实际效果:

可是在访问器对话框尺寸更改之后一些颗粒就会消退看不到,这个情况下必须加上1个恶性事件来监视访问器尺寸是不是更改:

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

随后必须来写winResize()涵数,这里必须留意1下,访问器更改的情况下开启resize恶性事件的次数会非常经常,略微挪动1下访问器的边沿便是开启几10次resize恶性事件,那末也就会再次测算几10次访问器尺寸,较为耗费特性,这个大伙儿能够检测1下,这里就立即说处理方式吧,实际上大家要的只是访问器更改后的最终的尺寸,至于正中间究竟更改了是多少次和大家沒有关联,因此大家能够在访问器对话框更改的情况下延缓200毫秒后实行测算访问器尺寸的恶性事件,假如在这期内1直开启resize恶性事件,那就1直往后面延缓200毫秒,听起来挺繁杂,实际上编码很简易:

var particle = [], w,h;     //颗粒数字能量数组,访问器宽高
var delay = 200,tid;        //延缓实行恶性事件和setTimeout恶性事件引入
function winResize(){
    clearTimeout(tid);
    tid = setTimeout(function(){
        getSize();          //获得访问器宽高,在文章内容最上面有详细介绍
    },delay)
}

这样全部的颗粒动漫都进行了,接下来便可以在颗粒之间画线了,大家上面界定的opt目标里边有1个minDistance自变量,当两个颗粒之间的连线小于这个值的情况下,大家就给她们之间画上线。

那末怎样测算两个颗粒之间的间距呢,大伙儿能够回想1下中学数学课第1课,勾股定理,直角3角形两个直角边的平方和等于第3条变的平方,看下面:

大家如今了解每一个颗粒的x轴和y轴的座标,那末大家便可以测算出两个点之间的间距了,写1个涵数,传入两个点,以下:

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

如今大家能够测算出两个点的间距,那末大家就测算出全部每一个颗粒同别的全部颗粒的间距,来明确它们之间是不是必须连线,自然假如全部颗粒的色调深层都1模1样,那就有点丑了,因此大家这里能够依据两个颗粒之间的间距来决策连线的全透明度,两个颗粒间距越近,越不全透明,间距越远,越全透明,超出1定间距就无法显示了。

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

上面传入的两个主要参数各自是1个点和全部点的数字能量数组,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⑻">
    <title>canvas颗粒动漫</title>
    <style>
        #canvas{
            position: absolute;
            display: block;
            left:0;
            top:0;
            background: #0f0f0f;
            z-index: ⑴;
        }
    </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;                //颗粒下1時刻在x轴的座标
            this.y += this.vector.y;                //颗粒下1時刻在y轴的座标
        }
        this.border = function(){               //分辨颗粒是都抵达界限
            if(this.x >= w || this.x<= 0){      //假如抵达上下界限,就让x轴的速率变成原先的负数
                this.vector.x *= ⑴;
            }
            if(this.y >= h || this.y <= 0){     //假如抵达左右界限,就让y轴的速率变成原先的负数
                this.vector.y *= ⑴;
            }
            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>

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。

上一篇:HTML5网页页面中尝试调起APP作用 返回下一篇:没有了