H5+canvas動態粒子背景


首先,效果圖為:

 H5代碼為

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

樣式設計CSS:

        <style>
            html {
                height: 100%
            }
            
            body {
                margin: 0;
                height: 100%;
                background: #fff;
            }

            canvas {
                display: block;
                width: 100%;
                height: 100%;
                position: absolute;
                top: 0;
                left: 0;
            }
        </style>

最重要的就是js代碼了。這里一步步來實現上述粒子效果。

通過看圖我們可以發現,就是由很多圓點跟線條組成的動態效果,那么要實現的就是繪制N個圓形,以及在一定距離內的兩個原點之間連線。

1.首先獲取到canvas對象,以及獲取屏幕的寬,高,創建一個圓點列表。

            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            
            var w = canvas.width = canvas.offsetWidth;
            var h = canvas.height = canvas.offsetHeight;
            var circles = [];

2.繪制N個原點,這里隨便多少個都可以,暫定60個。要繪制圓形,需要用到canvas的arc()方法,具體思路見canvas繪制圖形,那么我們這里定義一個方法

                function drawCircle(ctx) {
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.r, 0, 360);
                    ctx.fillStyle = 'rgba(204, 204, 204, 0.3)';
                    ctx.fill();
                }

該方法就可以通過canvas對象實現創建圓形了。那么看上述方法中的this.s, this.y表示的坐標,其實是這一方法定義在一個對象中,因為我們要創建很多圓形,所以定義了一個js對象,並且給該對象加入了畫圓,畫線,以及原點不斷移動的方法。

            //創建對象:圓
            //x, y為坐標點, r為半徑, _mx, _my為移動的距離
            function circle(x, y) {
                this.x = x;
                this.y = y;
                this.r = Math.random() * 10;
                this._mx = 1 - (Math.random() * 2);
                this._my = 1 - (Math.random() * 2);
                
                this.drawCircle = drawCircle;
                function drawCircle(ctx) {
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, this.r, 0, 360);
                    ctx.fillStyle = 'rgba(204, 204, 204, 0.3)';
                    ctx.fill();
                }
                
                this.move = move;
                function move(w, h) {
                    this._mx = (this.x < w && this.x > 0) ? this._mx : (-this._mx);
                    this._my = (this.y < h && this.y > 0) ? this._my : (-this._my);
                    this.x += this._mx / 2;
                    this.y += this._my / 2;
                }
                
                this.drawLine = drawLine;
                function drawLine(ctx, _circle) {
                    var dx = this.x - _circle.x;
                    var dy = this.y - _circle.y;
                    var d = Math.sqrt(dx * dx + dy * dy);
                    if (d < 150) {
                        ctx.beginPath();
                        ctx.moveTo(this.x, this.y);
                        ctx.lineTo(_circle.x, _circle.y);
                        ctx.strokeStyle = 'rgba(204, 204, 204, 0.3)';
                        ctx.stroke();
                    }
                }
            }

由上述代碼可以看到,只需要傳入相應的(x, y)坐標點,就可以創建一個原點。

其中r半徑是隨機函數產生的隨機數,所以最后生成的原點大小不一。

偏移量_mx,_my也是隨機數,由1 - (Math.random() * 2)可以看出偏移范圍為(-1, 1),所以我們可以看到有的點向左,有的向下,向左,向右,方向不一,能一定程度保證所有點均勻分布在屏幕中。

需要注意的是this.drawCircle = drawCircle;在對象中定義了方法之后還需要把方法添加到 JavaScript 對象。

移動方法move(),確保原點要在屏幕內移動,所以對於偏移量有個判斷,當坐標超出坐標范圍后,偏移量正負變換,即向之前移動方向的反方向移動。

兩點之間畫線的方法,這里設定兩點之間連線的范圍為0~150,超過150就不會再連線了。具體連線方法也可見canvas繪制圖形。方法中涉及到求兩點之間的直線距離,Math.sqrt(dx * dx + dy * dy),這個應該也好理解。

3. 定義了繪制圓點的方法,那么我們要再定義一個方法將所有的點畫出來。這里就要用到最開始定義的圓點列表circles。

<body onload="init(60)">
    ...
</body>
            function init(num) {
                for(var i = 0; i < num; i ++) {
                    circles.push(new circle(Math.random() * w, Math.random() * h));
                }
                draw();
            }

body上的onload方法表示網頁進入時觸發的方法,一打開網頁就要馬上加載init方法。

init方法,可以看到,是創建了60個circle實例push進原點列表中了,而創建的實例的坐標點都是隨機的范圍再(0, 0) ~ (w, h)。創建好實例后就要開始畫點了啊!調用draw方法。

            function draw() {
                ctx.clearRect(0, 0, w, h);
                for(var i = 0; i < circles.length; i ++) {
                    circles[i].move(w, h);
                    circles[i].drawCircle(ctx);
                    for(var j = i + 1; j < circles.length; j++) {
                        circles[i].drawLine(ctx, circles[j]);
                    }
                }
                requestAnimationFrame(draw);
            }

在上述方法中,遍歷所有原點,調用circle對象的方法,畫圓以及移動,里面的for循環表示每個當前點都與數組后面的點相連即可,即不需要考慮后面的點與前面的點相連問題,因為兩點之間連一次就可以了,所以j從1 + 1開始。

這里更新頁面用requestAnimationFrame替代setTimeout。

window.requestAnimationFrame = window.requestAnimationFrame 
                                        || window.mozRequestAnimationFrame 
                                        || window.webkitRequestAnimationFrame 
                                        || window.msRequestAnimationFrame;

 

4. 到目前為止,就實現了60個點在屏幕上移動,且150距離內的兩點會有連線,那么為了更好的體驗效果,我們可以加入鼠標進入屏幕的互動效果。

鼠標進入后會生成一個半徑確定的(這里假定8,都可以)不同顏色的原點,且該點在與任意點距離在150以內時要有連線。

那么,需要創建一個對象繼承circle,重寫畫圓方法。

            function currentCircle(x, y) {
                circle.call(this, x, y);
                
                this.drawCircle = drawCircle;
                function drawCircle(ctx) {
                    ctx.beginPath();
                    ctx.arc(this.x, this.y, 8, 0, 360);
                    ctx.fillStyle = 'rgba(255, 77, 54, 0.6)';
                    ctx.fill();
                }
            }

其實,這里也可以不定義這個對象,可以把circle對象改一下,將顏色也定為參數即可。

好了,對象定義好了,那么就要創建實例了,初始狀態為

            var current_circle = new currentCircle(0, 0);

 

在屏幕中移動以及離開屏幕的事件響應也可以有了。clientX為鼠標指針向對於瀏覽器頁面(或客戶區)的水平坐標。

            window.onmousemove = function(e) {
                e = e || window.event;
                current_circle.x = e.clientX;
                current_circle.y = e.clientY;
            }
            window.onmouseout = function() {
                current_circle.x = null;
                current_circle.y = null;
             }

最后,鼠標點與其他點的連線,修改draw方法

            function draw() {
                ctx.clearRect(0, 0, w, h);
                for(var i = 0; i < circles.length; i ++) {
                    circles[i].move(w, h);
                    circles[i].drawCircle(ctx);
                    for(var j = i + 1; j < circles.length; j++) {
                        circles[i].drawLine(ctx, circles[j]);
                    }
                } 
                if (current_circle.x) {
                    current_circle.drawCircle(ctx);
                    for (var k = 0; k < circles.length; k++) {
                        current_circle.drawLine(ctx, circles[k])
                    }
                }
                requestAnimationFrame(draw);
            }

加了一個判斷,如果current_circle的x坐標不為0了(初始狀態為0,見實例創建),那么就要畫鼠標點了,且遍歷所有的圓點,能連線的都連線。到這里,開頭的動圖上的效果都實現了。

最后,原碼下載地址GitHub:https://github.com/sakurayj/canvas

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM