本篇文章給大家?guī)砹薐avaScript中星空連線效果應(yīng)該怎樣呈現(xiàn)的相關(guān)知識(shí),希望對(duì)大家有幫助。
Javascript 星空連線效果的簡單實(shí)現(xiàn)
之前有見過非常炫酷的粒子連線的效果,這篇文章主要是實(shí)現(xiàn)一個(gè)簡單的星空連線的效果。
先貼一下大概的效果圖。
這個(gè)主要是用到了Html5中的canvas繪圖,關(guān)于canvas的基本使用這里就不展開介紹了,大家可以自行去了解。
然后采用的是requestAnimationFrame來進(jìn)行動(dòng)畫的繪制,而沒有采用定時(shí)器。
一、實(shí)現(xiàn)的效果
-
星星自動(dòng)生成,且星星的顏色,初始位置,移動(dòng)方向都是隨機(jī)的。
-
當(dāng)星星之間的距離小于給定值之后,會(huì)在星星之間生成連線。
-
鼠標(biāo)指針和星星之間的距離小于給定值之后,也會(huì)在星星和鼠標(biāo)指針之間生成連線。
二、實(shí)現(xiàn)的方法
通過canvas繪圖實(shí)現(xiàn)
定義星星類Star, 包括位置,半徑,顏色,移速等屬性與繪制和移動(dòng)等方法。
繪制星星,實(shí)現(xiàn)隨機(jī)移動(dòng)的效果。
在繪制星星之后計(jì)算每個(gè)星星之間的距離,在符合要求的星星之間繪制連線。
計(jì)算鼠標(biāo)指針和星星之間的距離,在符合要求的星星之間繪制連線。
繪制采用requestAnimationFrame
在主函數(shù)中執(zhí)行4,5的函數(shù)繼續(xù)進(jìn)行繪制
三、具體的實(shí)現(xiàn)
Html + Css
基本的文檔結(jié)構(gòu)非常簡單,創(chuàng)建一個(gè)canvas容器就可以了。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>星空連線</title> <style type="text/css"> * { margin: 0; padding: 0; } body, html { width: 100%; height: 100%; overflow: hidden; } #starry { position: absolute; background-color: #000000; } </style> </head> <body> <canvas id="starry"></canvas> </html>
定義星星類Star, 包括位置,半徑,顏色,移速等屬性與繪制和移動(dòng)等方法。
class Star { constructor() { this.x = randNum(3, canvas.width - 3); this.y = randNum(3, canvas.height - 3); this.r = randNum(1, 3); this.color = randColor(); this.speedX = randNum(-2, 2) * 0.2; this.speedY = randNum(-3, 3) * 0.2; } // 繪制每個(gè)星點(diǎn) draw() { //新建一條路徑 ctx.beginPath(); //調(diào)整透明度 ctx.globalAlpha = 1; // 填充顏色 ctx.fillStyle = this.color; // 繪制圓弧 ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2); // 填充 ctx.fill(); } // 星星移動(dòng) move() { this.x += this.speedX; this.y += this.speedY; //設(shè)置極限值 if (this.x <= 3 || this.x >= canvas.width - 3) this.speedX *= -1; if (this.y <= 3 || this.y >= canvas.height - 3) this.speedY *= -1; } } // 存儲(chǔ)小球 let stars = []; for (let i = 0; i < 150; i++) { let star = new Star(); // 存入數(shù)組 stars.push(star); }
繪制星星,實(shí)現(xiàn)隨機(jī)移動(dòng)的效果。
我們可以先實(shí)現(xiàn)星星的繪制,先暫時(shí)不管連線的效果。
function drawLine() { for (var i = 0; i < stars.length; i++) { stars[i].draw(); stars[i].move(); } }
在繪制星星之后計(jì)算每個(gè)星星之間的距離,在符合要求的星星之間繪制連線。
其實(shí)只要在上一步的函數(shù)中添加距離判斷和繪制連線的代碼就可以了。
function drawLine() { for (var i = 0; i < stars.length; i++) { stars[i].draw(); stars[i].move(); for (var j = 0; j < stars.length; j++) { if (i != j) { if (Math.sqrt(Math.pow((stars[i].x - stars[j].x), 2) + Math.pow((stars[i].y - stars[j].y), 2)) < 80) { ctx.beginPath(); ctx.moveTo(stars[i].x, stars[i].y); ctx.lineTo(stars[j].x, stars[j].y); ctx.strokeStyle = "white"; ctx.globalAlpha = 0.2; ctx.stroke(); } } } } }
計(jì)算鼠標(biāo)指針和星星之間的距離,在符合要求的星星之間繪制連線。
和繪制星星的方法差不多。
function mouseLine() { for (var i = 0; i < stars.length; i++) { if (Math.sqrt(Math.pow((stars[i].x - mouseX), 2) + Math.pow((stars[i].y - mouseY), 2)) < 120) { ctx.beginPath(); ctx.moveTo(stars[i].x, stars[i].y); ctx.lineTo(mouseX, mouseY); ctx.strokeStyle = "white"; ctx.globalAlpha = 0.8; ctx.stroke(); } } }
主函數(shù)進(jìn)行繪制
function main() { // 清除矩形區(qū)域 ctx.clearRect(0, 0, canvas.width, canvas.height); //鼠標(biāo)移動(dòng)繪制連線 mouseLine(); // 小球之間自動(dòng)連線 drawLine(); // 不斷重新執(zhí)行main(繪制和清除) window.requestAnimationFrame(main); }
一些輔助隨機(jī)函數(shù)
// 隨機(jī)函數(shù) function randNum(m, n) { return Math.floor(Math.random() * (n - m + 1) + m); } // 隨機(jī)顏色 function randColor() { return 'rgb(' + randNum(0, 255) + ',' + randNum(0, 255) + ',' + randNum(0, 255) + ')'; }
完整的代碼
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>星空連線</title> <style type="text/css"> * { margin: 0; padding: 0; } body, html { width: 100%; height: 100%; overflow: hidden; } #starry { position: absolute; background-color: #000000; } </style> </head> <body> <canvas id="starry"></canvas> <script type="text/javascript"> // 獲取canvas容器 let canvas = document.getElementById('starry'); // 獲取屏幕的寬高 canvas.width = document.documentElement.clientWidth; canvas.height = document.documentElement.clientHeight; // 設(shè)置繪制模式為2d let ctx = canvas.getContext('2d'); class Star { constructor() { this.x = randNum(3, canvas.width - 3); this.y = randNum(3, canvas.height - 3); this.r = randNum(1, 3); this.color = 'pink'; this.color = randColor(); this.speedX = randNum(-2, 2) * 0.2; this.speedY = randNum(-3, 3) * 0.2; } // 繪制每個(gè)星點(diǎn) draw() { //新建一條路徑 ctx.beginPath(); //調(diào)整透明度 ctx.globalAlpha = 1; // 填充顏色 ctx.fillStyle = this.color; // 繪制圓弧 ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2); // 填充 ctx.fill(); } // 小球移動(dòng) move() { this.x += this.speedX; this.y += this.speedY; //設(shè)置極限值 if (this.x <= 3 || this.x >= canvas.width - 3) this.speedX *= -1; if (this.y <= 3 || this.y >= canvas.height - 3) this.speedY *= -1; } } // 存儲(chǔ)小球 let stars = []; for (let i = 0; i < 150; i++) { let star = new Star(); // 存入數(shù)組 stars.push(star); } let mouseX; let mouseY; canvas.onmousemove = function (e) { var e = event || e; mouseX = e.offsetX; mouseY = e.offsetY; // console.log(mouseX+','+mouseY); } // 主要事件 main(); function mouseLine() { for (var i = 0; i < stars.length; i++) { if (Math.sqrt(Math.pow((stars[i].x - mouseX), 2) + Math.pow((stars[i].y - mouseY), 2)) < 120) { ctx.beginPath(); ctx.moveTo(stars[i].x, stars[i].y); ctx.lineTo(mouseX, mouseY); ctx.strokeStyle = "white"; ctx.globalAlpha = 0.8; ctx.stroke(); } } } // 在一定范圍內(nèi)劃線 function drawLine() { for (var i = 0; i < stars.length; i++) { stars[i].draw(); stars[i].move(); // for (var j = 0; j < stars.length; j++) { // if (i != j) { // if (Math.sqrt(Math.pow((stars[i].x - stars[j].x), 2) + Math.pow((stars[i].y - stars[j].y), 2)) < 80) { // ctx.beginPath(); // ctx.moveTo(stars[i].x, stars[i].y); // ctx.lineTo(stars[j].x, stars[j].y); // ctx.strokeStyle = "white"; // ctx.globalAlpha = 0.2; // ctx.stroke(); // } // } // } } } function main() { // 清除矩形區(qū)域 ctx.clearRect(0, 0, canvas.width, canvas.height); //鼠標(biāo)移動(dòng)繪制連線 mouseLine(); // 小球之間自動(dòng)連線 drawLine(); // 不斷重新執(zhí)行main(繪制和清除) window.requestAnimationFrame(main); } // 隨機(jī)函數(shù) function randNum(m, n) { return Math.floor(Math.random() * (n - m + 1) + m); } // 隨機(jī)顏色 function randColor() { return 'rgb(' + randNum(0, 255) + ',' + randNum(0, 255) + ',' + randNum(0, 255) + ')'; } </script> </body> </html>
結(jié)果如下:
【