亲宝软件园·资讯

展开

JavaScript+Canvas实现酷炫的粒子和流星效果

布尔科技技术团队 人气:0

一:粒子效果

<html>

<head>
  <meta charset="utf-8">
  <title>www.husonghe.com</title>
  <style>
    html {
      height: 100%;
      background-image: -webkit-radial-gradient(ellipse farthest-corner at center center, #1b44e4 0%, #020f3a 100%);
      background-image: radial-gradient(ellipse farthest-corner at center center, #1b44e4 0%, #020f3a 100%);
      cursor: move;
    }

    body {
      width: 100%;
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>


  <canvas id="canv" width="1920" height="572"></canvas>
  <script>
    var num = 200;
    var w = window.innerWidth;
    var h = window.innerHeight;
    var max = 100;
    var _x = 0;
    var _y = 0;
    var _z = 150;
    var dtr = function (d) {
      return d * Math.PI / 180;
    };

    var rnd = function () {
      return Math.sin(Math.floor(Math.random() * 360) * Math.PI / 180);
    };
    var dist = function (p1, p2, p3) {
      return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2));
    };

    var cam = {
      obj: {
        x: _x,
        y: _y,
        z: _z
      },
      dest: {
        x: 0,
        y: 0,
        z: 1
      },
      dist: {
        x: 0,
        y: 0,
        z: 200
      },
      ang: {
        cplane: 0,
        splane: 0,
        ctheta: 0,
        stheta: 0
      },
      zoom: 1,
      disp: {
        x: w / 2,
        y: h / 2,
        z: 0
      },
      upd: function () {
        cam.dist.x = cam.dest.x - cam.obj.x;
        cam.dist.y = cam.dest.y - cam.obj.y;
        cam.dist.z = cam.dest.z - cam.obj.z;
        cam.ang.cplane = -cam.dist.z / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.z * cam.dist.z);
        cam.ang.splane = cam.dist.x / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.z * cam.dist.z);
        cam.ang.ctheta = Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.z * cam.dist.z) / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.y * cam.dist.y + cam.dist.z * cam.dist.z);
        cam.ang.stheta = -cam.dist.y / Math.sqrt(cam.dist.x * cam.dist.x + cam.dist.y * cam.dist.y + cam.dist.z * cam.dist.z);
      }
    };

    var trans = {
      parts: {
        sz: function (p, sz) {
          return {
            x: p.x * sz.x,
            y: p.y * sz.y,
            z: p.z * sz.z
          };
        },
        rot: {
          x: function (p, rot) {
            return {
              x: p.x,
              y: p.y * Math.cos(dtr(rot.x)) - p.z * Math.sin(dtr(rot.x)),
              z: p.y * Math.sin(dtr(rot.x)) + p.z * Math.cos(dtr(rot.x))
            };
          },
          y: function (p, rot) {
            return {
              x: p.x * Math.cos(dtr(rot.y)) + p.z * Math.sin(dtr(rot.y)),
              y: p.y,
              z: -p.x * Math.sin(dtr(rot.y)) + p.z * Math.cos(dtr(rot.y))
            };
          },
          z: function (p, rot) {
            return {
              x: p.x * Math.cos(dtr(rot.z)) - p.y * Math.sin(dtr(rot.z)),
              y: p.x * Math.sin(dtr(rot.z)) + p.y * Math.cos(dtr(rot.z)),
              z: p.z
            };
          }
        },
        pos: function (p, pos) {
          return {
            x: p.x + pos.x,
            y: p.y + pos.y,
            z: p.z + pos.z
          };
        }
      },
      pov: {
        plane: function (p) {
          return {
            x: p.x * cam.ang.cplane + p.z * cam.ang.splane,
            y: p.y,
            z: p.x * -cam.ang.splane + p.z * cam.ang.cplane
          };
        },
        theta: function (p) {
          return {
            x: p.x,
            y: p.y * cam.ang.ctheta - p.z * cam.ang.stheta,
            z: p.y * cam.ang.stheta + p.z * cam.ang.ctheta
          };
        },
        set: function (p) {
          return {
            x: p.x - cam.obj.x,
            y: p.y - cam.obj.y,
            z: p.z - cam.obj.z
          };
        }
      },
      persp: function (p) {
        return {
          x: p.x * cam.dist.z / p.z * cam.zoom,
          y: p.y * cam.dist.z / p.z * cam.zoom,
          z: p.z * cam.zoom,
          p: cam.dist.z / p.z
        };
      },
      disp: function (p, disp) {
        return {
          x: p.x + disp.x,
          y: -p.y + disp.y,
          z: p.z + disp.z,
          p: p.p
        };
      },
      steps: function (_obj_, sz, rot, pos, disp) {
        var _args = trans.parts.sz(_obj_, sz);
        _args = trans.parts.rot.x(_args, rot);
        _args = trans.parts.rot.y(_args, rot);
        _args = trans.parts.rot.z(_args, rot);
        _args = trans.parts.pos(_args, pos);
        _args = trans.pov.plane(_args);
        _args = trans.pov.theta(_args);
        _args = trans.pov.set(_args);
        _args = trans.persp(_args);
        _args = trans.disp(_args, disp);
        return _args;
      }
    };

    (function () {
      "use strict";
      var threeD = function (param) {
        this.transIn = {};
        this.transOut = {};
        this.transIn.vtx = (param.vtx);
        this.transIn.sz = (param.sz);
        this.transIn.rot = (param.rot);
        this.transIn.pos = (param.pos);
      };

      threeD.prototype.vupd = function () {
        this.transOut = trans.steps(

          this.transIn.vtx,
          this.transIn.sz,
          this.transIn.rot,
          this.transIn.pos,
          cam.disp
        );
      };

      var Build = function () {
        this.vel = 0.04;
        this.lim = 360;
        this.diff = 200;
        this.initPos = 100;
        this.toX = _x;
        this.toY = _y;
        this.go();
      };

      Build.prototype.go = function () {
        this.canvas = document.getElementById("canv");
        this.canvas.width = window.innerWidth;
        this.canvas.height = window.innerHeight;
        this.$ = canv.getContext("2d");
        this.$.globalCompositeOperation = 'source-over';
        this.varr = [];
        this.dist = [];
        this.calc = [];

        for (var i = 0, len = num; i < len; i++) {
          this.add();
        }

        this.rotObj = {
          x: 0,
          y: 0,
          z: 0
        };
        this.objSz = {
          x: w / 5,
          y: h / 5,
          z: w / 5
        };
      };

      Build.prototype.add = function () {
        this.varr.push(new threeD({
          vtx: {
            x: rnd(),
            y: rnd(),
            z: rnd()
          },
          sz: {
            x: 0,
            y: 0,
            z: 0
          },
          rot: {
            x: 20,
            y: -20,
            z: 0
          },
          pos: {
            x: this.diff * Math.sin(360 * Math.random() * Math.PI / 180),
            y: this.diff * Math.sin(360 * Math.random() * Math.PI / 180),
            z: this.diff * Math.sin(360 * Math.random() * Math.PI / 180)
          }
        }));
        this.calc.push({
          x: 360 * Math.random(),
          y: 360 * Math.random(),
          z: 360 * Math.random()
        });
      };

      Build.prototype.upd = function () {
        cam.obj.x += (this.toX - cam.obj.x) * 0.05;
        cam.obj.y += (this.toY - cam.obj.y) * 0.05;
      };

      Build.prototype.draw = function () {
        this.$.clearRect(0, 0, this.canvas.width, this.canvas.height);
        cam.upd();
        this.rotObj.x += 0.1;
        this.rotObj.y += 0.1;
        this.rotObj.z += 0.1;

        for (var i = 0; i < this.varr.length; i++) {
          for (var val in this.calc[i]) {
            if (this.calc[i].hasOwnProperty(val)) {
              this.calc[i][val] += this.vel;
              if (this.calc[i][val] > this.lim) this.calc[i][val] = 0;
            }
          }

          this.varr[i].transIn.pos = {
            x: this.diff * Math.cos(this.calc[i].x * Math.PI / 180),
            y: this.diff * Math.sin(this.calc[i].y * Math.PI / 180),
            z: this.diff * Math.sin(this.calc[i].z * Math.PI / 180)
          };
          this.varr[i].transIn.rot = this.rotObj;
          this.varr[i].transIn.sz = this.objSz;
          this.varr[i].vupd();
          if (this.varr[i].transOut.p < 0) continue;
          var g = this.$.createRadialGradient(this.varr[i].transOut.x, this.varr[i].transOut.y, this.varr[i].transOut.p, this.varr[i].transOut.x, this.varr[i].transOut.y, this.varr[i].transOut.p * 2);
          this.$.globalCompositeOperation = 'lighter';
          g.addColorStop(0, 'hsla(255, 255%, 255%, 1)');
          g.addColorStop(.5, 'hsla(' + (i + 2) + ',85%, 40%,1)');
          g.addColorStop(1, 'hsla(' + (i) + ',85%, 40%,.5)');
          this.$.fillStyle = g;
          this.$.beginPath();
          this.$.arc(this.varr[i].transOut.x, this.varr[i].transOut.y, this.varr[i].transOut.p * 2, 0, Math.PI * 2, false);
          this.$.fill();
          this.$.closePath();
        }
      };
      Build.prototype.anim = function () {
        window.requestAnimationFrame = (function () {
          return window.requestAnimationFrame ||
            function (callback, element) {
              window.setTimeout(callback, 1000 / 60);
            };
        })();
        var anim = function () {
          this.upd();
          this.draw();
          window.requestAnimationFrame(anim);

        }.bind(this);
        window.requestAnimationFrame(anim);
      };

      Build.prototype.run = function () {
        this.anim();

        window.addEventListener('mousemove', function (e) {
          this.toX = (e.clientX - this.canvas.width / 2) * -0.8;
          this.toY = (e.clientY - this.canvas.height / 2) * 0.8;
        }.bind(this));
        window.addEventListener('touchmove', function (e) {
          e.preventDefault();
          this.toX = (e.touches[0].clientX - this.canvas.width / 2) * -0.8;
          this.toY = (e.touches[0].clientY - this.canvas.height / 2) * 0.8;
        }.bind(this));
        window.addEventListener('mousedown', function (e) {
          for (var i = 0; i < 100; i++) {
            this.add();
          }
        }.bind(this));
        window.addEventListener('touchstart', function (e) {
          e.preventDefault();
          for (var i = 0; i < 100; i++) {
            this.add();
          }
        }.bind(this));
      };
      var app = new Build();
      app.run();
    })();
    window.addEventListener('resize', function () {
      canvas.width = w = window.innerWidth;
      canvas.height = h = window.innerHeight;
    }, false);
  </script>
</body>

</html>

效果图

二:流星效果

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>一起来看流星雨</title>
</head>
<style type="text/css">
  body {
    background-color: black;
  }

  body,
  html {
    width: 100%;
    height: 100%;
    overflow: hidden;
  }
</style>

<body>
  <canvas id="stars"></canvas>
</body>

</html>
<script>
  var context;
  var arr = new Array();
  var starCount = 800;
  var rains = new Array();
  var rainCount = 20;
  //初始化画布及context
  function init() {
    //获取canvas
    var stars = document.getElementById("stars");
    windowWidth = window.innerWidth; //当前的窗口的高度
    stars.width = windowWidth;
    stars.height = window.innerHeight;
    //获取context
    context = stars.getContext("2d");
  }
  //创建一个星星对象
  var Star = function () {
    this.x = windowWidth * Math.random();//横坐标
    this.y = 5000 * Math.random();//纵坐标
    this.text = ".";//文本
    this.color = "white";//颜色
    //产生随机颜色
    this.getColor = function () {
      var _r = Math.random();
      if (_r < 0.5) {
        this.color = "#333";
      } else {
        this.color = "white";
      }
    }
    //初始化
    this.init = function () {
      this.getColor();
    }
    //绘制
    this.draw = function () {
      context.fillStyle = this.color;
      context.fillText(this.text, this.x, this.y);
    }
  }
  //画月亮
  function drawMoon() {
    var moon = new Image();
    moon.src = "./images/moon.jpg"
    context.drawImage(moon, -5, -10);
  }
  //页面加载的时候
  window.onload = function () {
    init();
    //画星星
    for (var i = 0; i < starCount; i++) {
      var star = new Star();
      star.init();
      star.draw();
      arr.push(star);
    }
    //画流星
    for (var i = 0; i < rainCount; i++) {
      var rain = new MeteorRain();
      rain.init();
      rain.draw();
      rains.push(rain);
    }
    drawMoon();//绘制月亮
    playStars();//绘制闪动的星星
    playRains();//绘制流星

  }
  //星星闪起来
  function playStars() {
    for (var n = 0; n < starCount; n++) {
      arr[n].getColor();
      arr[n].draw();
    }

    setTimeout("playStars()", 100);
  }

  /*流星雨开始*/
  var MeteorRain = function () {
    this.x = -1;
    this.y = -1;
    this.length = -1;//长度
    this.angle = 30; //倾斜角度
    this.width = -1;//宽度
    this.height = -1;//高度
    this.speed = 1;//速度
    this.offset_x = -1;//横轴移动偏移量
    this.offset_y = -1;//纵轴移动偏移量
    this.alpha = 1; //透明度
    this.color1 = "";//流星的色彩
    this.color2 = ""; //流星的色彩
    /****************初始化函数********************/
    this.init = function () //初始化
    {
      this.getPos();
      this.alpha = 1;//透明度
      this.getRandomColor();
      //最小长度,最大长度
      var x = Math.random() * 80 + 150;
      this.length = Math.ceil(x);
      //         x = Math.random()*10+30;
      this.angle = 30; //流星倾斜角
      x = Math.random() + 0.5;
      this.speed = Math.ceil(x); //流星的速度
      var cos = Math.cos(this.angle * 3.14 / 180);
      var sin = Math.sin(this.angle * 3.14 / 180);
      this.width = this.length * cos; //流星所占宽度
      this.height = this.length * sin;//流星所占高度
      this.offset_x = this.speed * cos;
      this.offset_y = this.speed * sin;
    }
    /**************获取随机颜色函数*****************/
    this.getRandomColor = function () {
      var a = Math.ceil(255 - 240 * Math.random());
      //中段颜色
      this.color1 = "rgba(" + a + "," + a + "," + a + ",1)";
      //结束颜色
      this.color2 = "black";
    }
    /***************重新计算流星坐标的函数******************/
    this.countPos = function ()//
    {
      //往左下移动,x减少,y增加
      this.x = this.x - this.offset_x;
      this.y = this.y + this.offset_y;
    }
    /*****************获取随机坐标的函数*****************/
    this.getPos = function () //
    {
      //横坐标200--1200
      this.x = Math.random() * window.innerWidth; //窗口高度
      //纵坐标小于600
      this.y = Math.random() * window.innerHeight; //窗口宽度
    }
    /****绘制流星***************************/
    this.draw = function () //绘制一个流星的函数
    {
      context.save();
      context.beginPath();
      context.lineWidth = 1; //宽度
      context.globalAlpha = this.alpha; //设置透明度
      //创建横向渐变颜色,起点坐标至终点坐标
      var line = context.createLinearGradient(this.x, this.y,
        this.x + this.width,
        this.y - this.height);
      //分段设置颜色
      line.addColorStop(0, "white");
      line.addColorStop(0.3, this.color1);
      line.addColorStop(0.6, this.color2);
      context.strokeStyle = line;
      //起点
      context.moveTo(this.x, this.y);
      //终点
      context.lineTo(this.x + this.width, this.y - this.height);
      context.closePath();
      context.stroke();
      context.restore();
    }
    this.move = function () {
      //清空流星像素
      var x = this.x + this.width - this.offset_x;
      var y = this.y - this.height;
      context.clearRect(x - 3, y - 3, this.offset_x + 5, this.offset_y + 5);
      //         context.strokeStyle="red";
      //         context.strokeRect(x,y-1,this.offset_x+1,this.offset_y+1);
      //重新计算位置,往左下移动
      this.countPos();
      //透明度增加
      this.alpha -= 0.002;
      //重绘
      this.draw();
    }
  }
  //绘制流星
  function playRains() {

    for (var n = 0; n < rainCount; n++) {
      var rain = rains[n];
      rain.move();//移动
      if (rain.y > window.innerHeight) {//超出界限后重来
        context.clearRect(rain.x, rain.y - rain.height, rain.width, rain.height);
        rains[n] = new MeteorRain();
        rains[n].init();
      }
    }
    setTimeout("playRains()", 2);
  }
/*流星雨结束*/
</script>

效果图

加载全部内容

相关教程
猜你喜欢
用户评论