解析
用了requstAniFrame,瀏覽器每隔1000/60ms進行重繪 ,然後使用迭代完成無限運動 ,每個粒子是用建構函式來建立。
總體的配置使用靜態類來做,值得一提的是滑鼠移入時附近粒子變大,我是在靜態類裡面存放了一個存放初始半徑的陣列,從裡面取值並賦值給存放粒子的陣列,為的是不讓粒子一直變大,形成555555的節奏
動畫原理:
- 全域性配置(粒子個數,存放粒子陣列,存放粒子半徑陣列,粒子之間的最小距離,粒子距離滑鼠的最小距離)
- 單個粒子配置,使用建構函式(顏色,半徑,速度),把粒子存入全域性配置中的存放粒子的陣列,對應半徑存入全域性配置中的存放粒子半徑的陣列
- 利用requstAniFrame進行重繪,每次先清除畫布,然後迴圈出全域性變數存放的值,進行移動等操作
效果
程式碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{
padding: 0;
margin: 0;
}
html,body{
width: 100%;
height: 100%;
overflow: hidden;
/*background-color: #020215;*/
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
<script type="text/javascript">
//相容requestAnimFrame
window.requestAnimFrame = ( function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ) {
window.setTimeout( callback, 1000 / 60 );
};
})();
//背景繪製函式
function drawBg(cvs)
{
cvs.beginPath();
cvs.fillStyle="#020215";
cvs.fillRect(0,0,wW,wH);
cvs.save();
}
//隨機數0-255(rgb)
function ran255(){
return Math.round(Math.random()*255);
}
//隨機顏色建構函式
function Color(){
this.r=ran255();
this.g=ran255();
this.b=ran255();
this.rgb="rgba("+this.r+","+this.g+","+this.b+",1)";
}
window.onload=function()
{
var can=document.getElementById("canvas");
can.width=wW=window.innerWidth;
can.height=wH=window.innerHeight;
var cvs=can.getContext("2d");
//繪製背景
drawBg(cvs);
//建立粒子配置(總體),靜態類
var Dots=
{
n:300,
minDis:50,
d_mouse:100,
array:[],
radiusArr:[]
}
//每個粒子的配置
function Dot()
{
this.color = new Color();//建立隨機顏色
//圓心座標
this.x = Math.round(Math.random()*wW);
this.y = Math.round(Math.random()*wH);
//速度(不同方向)
this.vx = (Math.random()-0.5)*3;
this.vy = (Math.random()-0.5)*3;
//隨機半徑
this.radius = Math.round(Math.random()*5);
}
//初始化
Dot.prototype.draw = function() {
cvs.beginPath();
cvs.fillStyle = this.color.rgb;
cvs.arc(this.x,this.y,this.radius,0,360,false);
cvs.fill();
};
//建立粒子並放入陣列
for(var i=0;i<Dots.n;i++)
{
var dotObj = new Dot();
Dots.array.push(dotObj);
Dots.radiusArr.push(dotObj.radius);
}
//畫出粒子
function drawDots()
{
drawBg(cvs);
for(var i=0;i<Dots.n;i++)
{
Dots.array[i].draw();
}
}
drawDots();
//移動粒子
function moveDots(){
for(var i=0;i<Dots.n;i++)
{
var dot = Dots.array[i];
//反彈判斷
if(dot.x <0 || dot.x>wW)
{
dot.vx=-dot.vx;
}
if(dot.y <0 || dot.y>wH)
{
dot.vy=-dot.vy;
}
dot.x += dot.vx;
dot.y += dot.vy;
}
}
//混合顏色
//連線
function connect()
{
function mixColor(dot1,dot2)
{
var color1=dot1.color;
var color2=dot2.color;
var r1=dot1.radius;
var r2=dot2.radius;
var r=Math.floor((color1.r*r1+color2.r*r2)/(r1+r2));
var g=Math.floor((color1.g*r1+color2.g*r2)/(r1+r2));
var b=Math.floor((color1.b*r1+color2.b*r2)/(r1+r2));
return "rgba("+r+","+g+","+b+",1)"
}
for(var i=0;i<Dots.n;i++)
{
for(var j=0;j<Dots.n;j++)
{
var dot1 = Dots.array[i];
var dot2 = Dots.array[j];
var color=mixColor(dot1,dot2);
if(Math.abs(dot1.x-dot2.x)<Dots.minDis && Math.abs(dot1.y-dot2.y)<Dots.minDis)
{
cvs.lineWidth=0.2;
cvs.beginPath();
cvs.strokeStyle=color;
cvs.moveTo(dot1.x,dot1.y);
cvs.lineTo(dot2.x,dot2.y);
cvs.stroke();
}
}
}
}
can.onmousemove=function(ev)
{
var ev=window.event || ev;
var pX=ev.pageX;
var pY=ev.pageY;
for(var i=0;i<Dots.n;i++)
{
if(Math.abs(Dots.array[i].x-pX)<Dots.d_mouse && Math.abs(Dots.array[i].y-pY)<Dots.d_mouse)
{
var r=Dots.radiusArr[i]*5;
Dots.array[i].radius=r;
}
else{
Dots.array[i].radius=Dots.radiusArr[i];
}
}
}
//無限運動
function infinateDot()
{
cvs.clearRect(0,0,wW,wH);
moveDots();
drawDots();
connect();
requestAnimationFrame(infinateDot)
}
infinateDot();
}
</script>
複製程式碼