【问题标题】:How to create a Confetti effect using JavaScript如何使用 JavaScript 创建五彩纸屑效果
【发布时间】:2018-06-02 07:55:18
【问题描述】:

我想创建一个五彩纸屑效果(附上屏幕截图),其中薄片应该是 TRIANGULAR 形状(目前它们是 RECTANGULAR)。我正在使用以下 javascript 代码来获得效果。但是,我希望在打开网页时薄片开始从上到下掉落。现在,当我们打开页面的那一刻,页面被薄片淹没了。我在看,我怎样才能使屏幕空白并使薄片慢慢下降。谁能帮我整理一下这个效果:

window.onload = function() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var W = window.innerWidth;
  var H = window.innerHeight;
  canvas.width = W;
  canvas.height = H;

  var mp = 1000; //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() * 18 + 1, //radius
      d: Math.random() * mp, //density
      color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)",
      tilt: Math.floor(Math.random() * 5) - 5
    });
  }

  //Lets draw the flakes
  function draw() {
    ctx.clearRect(0, 0, W, H);
    for (var i = 0; i < mp; i++) {
      var p = particles[i];
      ctx.beginPath();
      ctx.lineWidth = p.r;
      ctx.strokeStyle = p.color; // Green path
      ctx.moveTo(p.x, p.y);
      ctx.lineTo(p.x + p.tilt + p.r / 2, p.y + p.tilt);
      ctx.stroke(); // Draw it
    }

    update();
  }

  var angle = 0;

  function update() {
    angle += 0.01;
    for (var i = 0; i < mp; i++) {
      var p = particles[i];
      p.y += Math.cos(angle + p.d) + 1 + p.r / 2;
      p.x += Math.sin(angle) * 2;
      if (p.x > W + 5 || p.x < -5 || p.y > H) {
        if (i % 3 > 0) //66.67% of the flakes
        {
          particles[i] = {
            x: Math.random() * W,
            y: -10,
            r: p.r,
            d: p.d,
            color: p.color,
            tilt: p.tilt
          };
        }
      }
    }
  }
  setInterval(draw, 20);
}
&lt;canvas id="canvas"&gt;&lt;/canvas&gt;

小提琴JS Fiddle link

最终目标:Image

【问题讨论】:

  • 你能把它做成一个工作的sn-p吗?
  • @TemaniAfif 这是fiddle。它的作用与描述的一样,自上而下的效果。有什么问题?
  • @TemaniAfif 谢谢。我需要改变两件事: 1. 薄片的形状从矩形变为三角形。 2. 由于页面加载时屏幕上加载了薄片,所以我希望薄片从页面顶部缓慢下降。谢谢
  • @MatthewZackschewski 你能建议一下吗?
  • 我现在正试图获得一个有效的小提琴,但我只是使用这个site 来尝试改变你的 draw() 函数来进行填充而不是描边。尚未成功

标签: javascript jquery css html html5-canvas


【解决方案1】:

要制作三角形,您需要画一个形状,而不是画一条粗线。

// Rectangle
ctx.strokeStyle = p.color;
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.x + p.tilt + p.r / 2, p.y + p.tilt);
ctx.stroke();

// Triangle
ctx.fillStyle = p.color;
ctx.moveTo(p.x, p.y);
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.x + 10, p.y);
ctx.lineTo(p.x + 5, p.y + 10);
ctx.fill();

以下代码已更新以完成您想要的两件事:

  • 矩形变为三角形
  • 页面以 5 个三角形开始,然后使用setTimeout 每十分之一秒添加一个雪花。 (也可以删除循环以从 0 个雪花开始,或者可以通过更改超时来更快/更慢地添加雪花。)

小提琴:https://jsfiddle.net/72dun3fx/13/

window.onload = function() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var W = window.innerWidth;
  var H = window.innerHeight;
  var particles = [];
  var angle = 0;
  canvas.width = W;
  canvas.height = H;

  // Add starting particles
  for (var i = 0; i < 5; i++) {
    addParticle();
  }
  // Add a particle every tenth of a second
  setInterval(addParticle, 100);
  // Update the particles so they fall
  setInterval(draw, 20);

  // Add a single particle
  function addParticle() {
    if (particles.length > 1000) {
      return false;
    }

    particles.push({
      x: Math.random() * W, //x-coordinate
      y: Math.random() * H, //y-coordinate
      r: Math.random() * 18 + 1, //radius
      d: Math.random() * particles.length, //density
      color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)",
      tilt: Math.floor(Math.random() * 5) - 5
    });
  }

  /* Draw the particles */
  function draw() {
    ctx.clearRect(0, 0, W, H);
    for (var i = 0; i < particles.length; i++) {
      var p = particles[i];
      ctx.beginPath();
      ctx.lineWidth = p.r;
      ctx.fillStyle = p.color;
      ctx.moveTo(p.x, p.y);
      ctx.beginPath();
      ctx.moveTo(p.x, p.y);
      ctx.lineTo(p.x + 10, p.y);
      ctx.lineTo(p.x + 5, p.y + 10);
      ctx.fill();
    }

    update();
  }

  function update() {
    angle += 0.01;
    for (var i = 0; i < particles.length; i++) {
      var p = particles[i];
      p.y += Math.cos(angle + p.d) + 1 + p.r / 2;
      p.x += Math.sin(angle) * 2;
      if (p.x > W + 5 || p.x < -5 || p.y > H) {
        if (i % 3 > 0) //66.67% of the flakes
        {
          particles[i] = {
            x: Math.random() * W,
            y: -10,
            r: p.r,
            d: p.d,
            color: p.color,
            tilt: p.tilt
          };
        }
      }
    }
  }
};
&lt;canvas id="canvas"&gt;&lt;/canvas&gt;

【讨论】:

  • 感谢 Alison 的更新,它解决了一半的问题。我的最终目标是屏幕截图(附在帖子上)。根据您的经验还有什么其他建议吗?
【解决方案2】:

我对上面的答案进行了微调,使其更符合您的要求。编辑 Y 组件,使三角形不能越过画布的中间。其次,使三角形从画布的顶部开始。希望这会有所帮助。

编辑:这是您要找的吗?
旁注:我在 draw() 函数中添加了 Math.random() * 7,因为我认为效果很酷,但是如果您不喜欢它,请将其替换为 10(这是之前设置的。

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var W = window.innerWidth;
var H = window.innerHeight - 30;
canvas.width = W;
canvas.height = H;

var particles = [];
for (var i = 0; i < 100; i++) {
  addParticle();
}
setInterval(addParticle(), 10);

/* Add a single particle */
function addParticle() {
  if (particles.length > 1000) {
    return false;
  }

  particles.push({
    x: Math.random() * W, //x-coordinate
    y: H, //y-coordinate
    r: Math.random() * 18 + 1, //radius
    d: Math.random() * particles.length, //density
    color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)",
    tilt: Math.floor(Math.random() * 5) - 5
  });
}

/* Draw the particles */
function draw() {
  ctx.clearRect(0, 0, W, H);
  for (var i = 0; i < particles.length; i++) {
    var p = particles[i];
    ctx.beginPath();
    ctx.lineWidth = p.r;
    ctx.fillStyle = p.color;
    ctx.moveTo(p.x, p.y);
    ctx.beginPath();
    ctx.moveTo(p.x, p.y);
    ctx.lineTo(p.x + 10, p.y);
    ctx.lineTo(p.x + 5, p.y + (Math.random() * 7));
    ctx.fill();
  }

  update();
}

var angle = 0.02;

function update() {
  for (var i = 0; i < particles.length; i++) {
    var p = particles[i];
    p.y += Math.cos(angle) + 1 + p.r / 10;
    p.x += Math.sin(angle) * 2;
    if (p.x > W + 5 || p.x < -5 || p.y > H) {
      if (i % 3 > 0) //66.67% of the flakes
      {
        particles[i] = {
          x: Math.random() * W,
          y: -10,
          r: p.r,
          d: p.d,
          color: p.color,
          tilt: p.tilt
        };
      }
    }
  }
}
setInterval(draw, 20);
canvas {
  z-index: 999;
}

.thankYouBanner {
  position:absolute;
  height:30px;
  bottom:20%;
  left:50%;
  z-index: 1000;
}

.thankYouBanner h2 {
  position:relative;
  text-align:center;
  width: 100%;
  left: -50%;
  color: #fff;
  background-color: rgba(0,0,0,0.6);
  box-shadow: 0 0 15px 10px #fff;
  padding-left: 10px;
  padding-right: 10px;
  padding-top: 5px;
  padding-bottom: 5px;
  border-radius: 10px;
}
<canvas id="canvas"></canvas>
<div class="thankYouBanner">
  <h2>
    Thank You, John Doh
  </h2>
</div>

【讨论】:

  • 感谢马修。我附上了我的问题的屏幕截图。我正在努力得到这个结果。您能否根据您的经验分享解决方案。谢谢
  • 已编辑答案。 Lmk 如果那是你要找的东西
  • @Victor 如果以上答案足够,请将其标记为正确答案。谢谢!
猜你喜欢
  • 2021-07-17
  • 2018-02-11
  • 2015-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多