Heim > Web-Frontend > H5-Tutorial > Ausführliche Erläuterung der gemeinsamen Nutzung von Beispielcode zum Erstellen dynamischer Partikelgitteranimationen mit HTML5 Canvas

Ausführliche Erläuterung der gemeinsamen Nutzung von Beispielcode zum Erstellen dynamischer Partikelgitteranimationen mit HTML5 Canvas

黄舟
Freigeben: 2018-05-28 17:48:39
Original
3246 Leute haben es durchsucht

Dieser Artikel stellt hauptsächlich die Verwendung von HTML5 Canvas zum Erstellen dynamischer Partikelgitter Animationen vor. Er ist von großem praktischen Wert und Freunde in Not können sich darauf beziehen Es.

Ich habe kürzlich eine sehr coole Partikelgitteranimation gesehen, also habe ich selbst eine erstellt. Sie eignet sich gut als Hintergrund. Da CSDN keine Bilder hochladen kann, die größer als 2 M sind, schneide ich einfach ein statisches Bild aus:

Beginnen wir damit, wie man diesen Effekt erzielt:

Ausführliche Erläuterung der gemeinsamen Nutzung von Beispielcode zum Erstellen dynamischer Partikelgitteranimationen mit HTML5 Canvas

Zuallererst von Natürlich ist es Zeit, eine Leinwand hinzuzufügen:

<canvas id="canvas"></canvas>
Nach dem Login kopieren

Das Folgende ist der Stil:

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

Der Z-Index der Leinwand oben: -1 kann unter einigen Elementen platziert werden als ein Hintergrund.

Um sicherzustellen, dass die Leinwand den gesamten Browser ausfüllen kann, müssen Breite und Höhe der Leinwand mit denen des Browsers übereinstimmen:

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

Breite und Höhe oben stellen die Breite bzw. Höhe des Browsers dar.

Nachdem wir die Breite und Höhe des Browsers ermittelt haben, besteht der nächste Schritt darin, die Partikel hineinzuziehen. Hier müssen wir im Voraus einige Partikelparameter definieren:

var opt = {
    particleAmount: 50,         //粒子个数
    defaultSpeed: 1,            //粒子运动速度
    variantSpeed: 1,            //粒子运动速度的变量
    particleColor: "rgb(32,245,245)",       //粒子的颜色
    lineColor:"rgb(32,245,245)",            //网格连线的颜色
    defaultRadius: 2,           //粒子半径
    variantRadius: 2,           //粒子半径的变量
    minDistance: 200            //粒子之间连线的最小距离
};
Nach dem Login kopieren

Die oben genannten Geschwindigkeitsvariablen und Radiusvariablen sind beides. Dies soll sicherstellen, dass die Größe und Geschwindigkeit der Partikel nicht genau gleich sind.

Dann erstellen wir eine Klasse, um die Partikel zu initialisieren, also habe ich Kommentare hinzugefügt:

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();
    }
}
Nach dem Login kopieren
Die Anfangsgeschwindigkeit jedes Partikels und Winkel werden zufällig generiert und die Farbe der Partikel wird durch die entsprechenden Einstellungsoptionen bestimmt.

2. This.vector wird verwendet, um die Bewegungsrichtung von Partikeln zu speichern: Wenn this.vector.x 1 ist, bewegen sich die Partikel nach rechts; wenn es -1 ist, bewegen sich die Partikel nach links. Wenn this.vector.y negativ ist, bewegt sich das Teilchen ebenfalls nach oben, und wenn es positiv ist, bewegt sich das Teilchen nach unten.

Dieses Update wird verwendet, um die Koordinaten der nächsten Position jedes Partikels zu aktualisieren. Zunächst wird eine Kantenerkennung durchgeführt. Wenn die Bewegung des Partikels die Größe der Leinwand überschreitet, wird der Richtungsvektor mit -1 multipliziert, um die entgegengesetzte Bewegungsrichtung zu erzeugen.

3. Die Fensterskalierung kann dazu führen, dass Partikel über die Grenze hinausgehen, sodass die Kantenerkennungsfunktion sie nicht erfassen kann. Daher sind eine Reihe von if-Anweisungen erforderlich, um diese Situation zu erkennen und die Partikelposition auf die aktuelle Grenze zurückzusetzen der Leinwand.

4. Der letzte Schritt besteht darin, diese Punkte auf die Leinwand zu zeichnen.

Die Partikelklasse wurde geschrieben, zeichnen wir sie unten:

function init(){
   getSize();
   for(let i = 0;i<opt.particleAmount; i++){
        particle.push(new Partical());
   }
   loop();
}
Nach dem Login kopieren
Das opt.particleAmount-Partikel

object wurde oben initialisiert, aber das Objekt wird initialisiert, aber es wurde nicht gezeichnet. Hier ist die Schleifenfunktion:

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);
}
Nach dem Login kopieren
Jedes Mal, wenn die Funktion loop() ausgeführt wird, wird der Inhalt auf der Leinwand gelöscht und anschließend werden die Partikelkoordinaten durch die Aktualisierung neu berechnet ()-Funktion des Partikelobjekts. Schließlich werden Partikel über die Funktion draw() des Partikelobjekts gezeichnet. Zu diesem Zeitpunkt ist der Effekt wie folgt:

Ausführliche Erläuterung der gemeinsamen Nutzung von Beispielcode zum Erstellen dynamischer Partikelgitteranimationen mit HTML5 Canvas

Einige Partikel verschwinden jedoch, nachdem die Größe des Browserfensters geändert wurde. Zu diesem Zeitpunkt müssen Sie ein

hinzufügen Ereignis Überwachen Sie, ob sich die Browsergröße ändert:

window.addEventListener("resize",function(){
    winResize()
},false);
Nach dem Login kopieren
Dann müssen Sie die Funktion winResize() schreiben. Hier müssen Sie darauf achten, wie oft sich das Größenänderungsereignis ändert Wenn der Browser leicht verschoben wird, wird er Dutzende Male neu berechnet, was die Leistung beeinträchtigt. Lassen Sie uns hier über die Lösung sprechen. Tatsächlich wollen wir nur die Browsergröße nach der Änderung. Die endgültige Größe hat nichts damit zu tun, wie oft sie sich in der Zwischenzeit geändert hat, sodass wir das Ereignis zur Berechnung der Browsergröße um 200 Millisekunden verzögern können Wenn sich das Browserfenster während dieses Zeitraums kontinuierlich ändert, dauert es 200 Millisekunden. Tatsächlich ist der Code sehr einfach:

var particle = [], w,h;     //粒子数组,浏览器宽高
var delay = 200,tid;        //延缓执行事件和setTimeout事件引用
function winResize(){
    clearTimeout(tid);
    tid = setTimeout(function(){
        getSize();          //获取浏览器宽高,在文章最上面有介绍
    },delay)
}
Nach dem Login kopieren
Auf diese Weise , alle Partikelanimationen sind abgeschlossen, und dann können Sie Linien zwischen Partikeln zeichnen, wie wir oben definiert haben. Es gibt eine minDistance-Variable im opt-Objekt. Wenn die Linie zwischen zwei Partikeln kleiner als dieser Wert ist, zeichnen wir eine Linie zwischen ihnen.

Wie berechnet man also den Abstand zwischen zwei Teilchen? Sie können sich an die erste Lektion der Mathematik der Mittelstufe erinnern, den Satz des Pythagoras ist gleich dem Quadrat der dritten Variablen. Siehe unten:

Ausführliche Erläuterung der gemeinsamen Nutzung von Beispielcode zum Erstellen dynamischer Partikelgitteranimationen mit HTML5 Canvas

Wir kennen jetzt die Koordinaten der x-Achse und der y-Achse jedes Partikels und können dann berechnen Geben Sie den Abstand zwischen den beiden Punkten ein und schreiben Sie eine Funktion. Übergeben Sie zwei Punkte wie folgt:

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

现在我们可以计算出两个点的距离,那么我们就计算出所有每个粒子同其他所有粒子的距离,来确定它们之间是否需要连线,当然如果所有粒子的颜色深度都一模一样,那就有点丑了,所以我们这里可以根据两个粒子之间的距离来决定连线的透明度,两个粒子距离越近,越不透明,距离越远,越透明,超过一定距离就不显示了。

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();
        }
    }
}
Nach dem Login kopieren

上面传入的两个参数分别是一个点和整个点的数组,let opacity = 1 -distance/opt.minDistance;用于判断连线之间的透明度同时也判断了距离,距离大于opt.minDistance时,opacity为负,下面判断时就过滤掉了,上面的颜色用到了正则表达式,需要先解析最上面opt对象里给出的颜色,然后再加上透明度,这段代码如下:

var line = opt.lineColor.match(/\d+/g);
Nach dem Login kopieren

最后在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);
    }
Nach dem Login kopieren

需要指出的是:如果添加过多的点和/或过多的连接距离(连接距离会创建过多的线条),动画也会扛不住。当视口变窄时最好降低粒子的运动速度:粒子的尺寸越小,在愈加狭窄空间内的移动速度貌似会越快。

显示整段代码:




    
    canvas粒子动画
    


<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>

Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung der gemeinsamen Nutzung von Beispielcode zum Erstellen dynamischer Partikelgitteranimationen mit HTML5 Canvas. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage