canvas动画特效 之 星空

解析

用了requstAniFrame,浏览器每隔1000/60ms进行重绘 ,而后使用迭代完成无限运动 ,每一个粒子是用构造函数来建立。
整体的配置使用静态类来作,值得一提的是鼠标移入时附近粒子变大,我是在静态类里面存放了一个存放初始半径的数组,从里面取值并赋值给存放粒子的数组,为的是不让粒子一直变大,造成555555的节奏javascript

动画原理:

  1. 全局配置(粒子个数,存放粒子数组,存放粒子半径数组,粒子之间的最小距离,粒子距离鼠标的最小距离)
  2. 单个粒子配置,使用构造函数(颜色,半径,速度),把粒子存入全局配置中的存放粒子的数组,对应半径存入全局配置中的存放粒子半径的数组
  3. 利用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>
复制代码
相关文章
相关标签/搜索