HTML5 Canvas下降五彩纸屑/雪花多个对象

时间:2016-04-07 19:46:13

标签: javascript html5 canvas snowfall

我从这个例子开始:http://thecodeplayer.com/walkthrough/html5-canvas-snow-effect

我试图添加多种形状的坠落物体。然而,只有最后一个我打电话似乎工作。它会在屏幕上覆盖其他人。

我尝试做的另一件事是将数组中的颜色随机化,但是当我添加一个随机函数时,我会得到一个疯狂的变色效果。我不完全了解发生了什么,这是我第一次潜入画布。看起来每帧都重新绘制了对象。这适用于雪,因为它是所有的白色圆圈。

知道如何进行这些更改吗?这是我的代码(SEIZURE WARNING!):http://codepen.io/paper_matthew/pen/vGpyeq

HTML

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

<div id="party-info">

  <h2>PARTY!!</h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt impedit animi enim iste repellat aliquam laborum consequuntur asperiores neque eos praesentium quis, consectetur cupiditate suscipit cum inventore excepturi? Vel, laudantium.</p>
</div>

CSS

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  background-color: #fff;
  overflow: hidden;
}

#confetti {
  position: relative;
  top:0;
  left: 0;
  z-index: 1;
}

#party-info {
  position: absolute;
  background: #fff;
  padding: 20px;
  margin: 0 auto;
  height: 200px;
  top: 0;
  left: 0;
  right: 0;
  bottom:0;
  text-align: center;
  width: 400px;
  z-index: 22;
  color: gray;
}

的Javascript

window.onload = function() {
  //canvas init
  var canvas = document.getElementById("confetti");
  var ctx = canvas.getContext("2d");

  COLORS = [
    [238, 96, 169],
    [68, 213, 217],
    [245, 187, 152],
    [144, 148, 188],
    [235, 234, 77]
  ];

  //canvas dimensions
  var W = window.innerWidth;
  var H = window.innerHeight;
  canvas.width = W;
  canvas.height = H;

  //particles
  var mp = 100; //max particles
  var particles = [];
  for (var i = 0; i < mp; i++) {
    particles.push({
      x: Math.random() * W, //x-coordinate
      y: Math.random() * H, //y-coordinate
      r: Math.random() * 4 + 1, //radius
      d: Math.random() * mp //density
    })
  }

  // Draw the shapes
  function drawCircle() {

    ctx.clearRect(0, 0, W, H);
    ctx.fillStyle = "rgba(" + COLORS[Math.floor(Math.random()*5+0)] + ", 0.8)";
    ctx.beginPath();
    for (var i = 0; i < mp; i++) {
      var p = particles[i];

      ctx.moveTo(p.x, p.y);
      ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);

    }
    ctx.fill();
    update();

  }

  function drawTriangle() {

    ctx.clearRect(0, 0, W, H);
    ctx.fillStyle = "rgba(" + COLORS[2] + ", 0.8)";
    ctx.beginPath();
    for (var i = 0; i < mp; i++) {
      var p = particles[i];

      ctx.moveTo(p.x, p.y);
      ctx.lineTo(p.x + 15, p.y);
      ctx.lineTo(p.x + 15, p.y + 15);
      ctx.closePath();

    }
    ctx.fill();
    update();

  }

  function drawLine() {
    ctx.clearRect(0, 0, W, H);
    ctx.strokeStyle = "rgba(" + COLORS[3] + ", 0.8)";
    ctx.beginPath();
    for (var i = 0; i < mp; i++) {
      var p = particles[i];

      ctx.moveTo(p.x, p.y);
      ctx.lineTo(p.x, p.y + 20);
      ctx.lineWidth = 2;

    }
    ctx.stroke();
    update();
  }

  function update() {

    for (var i = 0; i < mp; i++) {
      var p = particles[i];
      p.y += Math.cos(p.d) + 1 + p.r / 2;
      p.x += Math.sin(0) * 2;

      if (p.x > W + 5 || p.x < -5 || p.y > H) {
        particles[i] = {
          x: Math.random() * W,
          y: -10,
          r: p.r,
          d: p.d
        };
      }
    }
  }

  function drawShapes() {
    drawTriangle();
    drawLine();
    drawCircle();
  }

  //animation loop
  setInterval(drawShapes, 33);

}

2 个答案:

答案 0 :(得分:1)

你正在调用drawShapes(),它会在彼此之后立即绘制3个形状。 Var ctx是全局的,因此每次绘制都会立即覆盖前一个绘图。

答案 1 :(得分:1)

画布的任何动画循环都涉及对update()和draw()的重复调用。您应该更新模型,然后绘制到画布。冲洗并重复。

我已经创建了一个新的Javascript文件来与您的HTML / CSS一起使用。它允许创建一个Particle对象,它可以是以下三种类型之一:

  1. 三角
  2. 然后我创建了这些对象类型的数组。每种类型的三分之一填充到阵列中。然后我简单地循环遍历这些对象,并分别在我的更新和绘制函数中调用动画循环中每个对象的更新和绘制方法。

    这里是代码,粒子数减少到40,以提高平滑的动画速度:

    function Particle(ctx, width, height, maxParticles, particleType) {
        COLORS = [
            [238, 96, 169],
            [68, 213, 217],
            [245, 187, 152],
            [144, 148, 188],
            [235, 234, 77]
        ];
        var ctx = ctx;
        var width = width;
        var height = height;
        var maxParticles = maxParticles;
        var particleType = particleType;
        var color = COLORS[Math.floor(Math.random() * 5)];
    
        var x = Math.random() * width;
        var y = Math.random() * height;
        var r = Math.random() * 4 + 1;
        var d = Math.random() * maxParticles;
    
        this.update = function() {
            y += Math.cos(d) + 1 + (r / 2);
            x += Math.sin(0) * 2;
            if (x > width + 5 || x < -5 || y > height) {
                x = Math.random() * width;
                y = -10;
            }
        };
    
        this.draw = function() {
            ctx.save();
            ctx.strokeStyle = "rgba(" + color + ", 0.8)";
            ctx.fillStyle = ctx.strokeStyle;
            ctx.beginPath();
            for (var i = 0; i < maxParticles; i++) {
                ctx.moveTo(x, y);
                switch (particleType) {
                case 1:
                    ctx.arc(x, y, r, 0, Math.PI * 2, false);
                    ctx.fill();
                    break;
                case 2:
                    ctx.lineTo(x + 15, y);
                    ctx.lineTo(x + 15, y + 15);
                    ctx.fill();
                    break;
                case 3:
                    ctx.lineWidth = 2;
                    ctx.lineTo(x, y + 20);
                    ctx.stroke();
                    break;
                default:
                    console.log('Unable to draw: undefined particle type [' + particleType + ']');
                    break;
                }
            }
    
            ctx.restore();
        };
    }
    
    window.onload = function() {
        //canvas init
        var canvas = document.getElementById("confetti");
        var ctx = canvas.getContext("2d");
    
        //canvas dimensions
        var W = window.innerWidth;
        var H = window.innerHeight;
        canvas.width = W;
        canvas.height = H;
    
        //particles
        var mp = 40;
        var particles = [];
        for (var i = 0; i < mp; i++) {
            var type = Math.floor(i * 3 / mp) + 1;
            particles.push(new Particle(ctx, W, H, particles.length, type));
        }
    
        function drawShapes() {
            update();
            draw();
            setTimeout(drawShapes, 20);
        }
    
        function update() {
            for (var key in particles) {
                particles[key].update();
            }
        }
    
        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            for (var key in particles) {
                particles[key].draw();
            }
        }
    
        //animation loop
        drawShapes();
    }