【问题标题】:Why are my particles speeding up when I press button in JavaScript?当我在 JavaScript 中按下按钮时,为什么我的粒子会加速?
【发布时间】:2019-09-30 08:11:52
【问题描述】:

我正在制作一个五彩纸屑发射器,它可以创建正方形并将它们放置在屏幕顶部,它们每个都有一定的重力和朝向侧面的方向。我有一个按钮,一次可以制作 100 个。然而,每次我按下按钮时,它都会创建新的,但也会加快现有方块的移动。

var width1 = window.innerWidth || document.documentElement.clientWidth ||
  document.body.clientWidth;
var height1 = window.innerHeight || document.documentElement.clientHeight ||
  document.body.clientHeight;
let canvas = document.getElementById('confetti');
let ctx = canvas.getContext('2d');
canvas.width = width1;
canvas.height = height1;
let pieces = [];
let numberOfPieces = 100;
let lastUpdateTime = Date.now();
var a = 0;
var intervalID;

function randomColor() {
  let colors = ['#999999ff', '#b7b7b7ff', '	#D3D3D3', '#ffff00 ', '#d9d9d9ff'];
  return colors[Math.floor(Math.random() * colors.length)];
}

function update() {
  let now = Date.now(),
    dt = now - lastUpdateTime;

  for (let i = pieces.length - 1; i >= 0; i--) {
    let p = pieces[i];

    if (p.y > canvas.height) {
      pieces.splice(i, 1);
      continue;
    }

    p.y += p.gravity * dt;
    p.rotation += p.rotationSpeed * dt;
    p.x += p.direction;
  }


  if (pieces.length < numberOfPieces) {
    for (var b = pieces.length; b < numberOfPieces; b++) {
      pieces.push(new Piece(Math.random() * canvas.width, -20));
      b--;
      numberOfPieces--;
    }
  }
  lastUpdateTime = now;
  a++;
  if (a >= 1) {
    numberOfPieces = 0;
    //console.log("number of pieces: " + numberOfPieces + " pieces.length: " + pieces.length);
  }
}

function draw() {

  ctx.clearRect(0, 0, canvas.width, canvas.height);

  pieces.forEach(function(p) {
    ctx.save();

    ctx.fillStyle = p.color;

    ctx.translate(p.x + p.size / 2, p.y + p.size / 2);
    ctx.rotate(p.rotation);

    ctx.fillRect(-p.size / 2, -p.size / 2, p.size, p.size);

    ctx.restore();
  });

  requestAnimationFrame(draw);
}

function Piece(x, y) {
  this.x = x;
  this.y = y;
  this.size = (Math.random() * 0.5 + 0.75) * 15;
  this.gravity = (Math.random() * 0.5 + 0.75) * 0.15;
  var c = Math.random()
  if (c > 0.5) {
    this.direction = -(Math.random() * 0.6);
  } else {
    this.direction = (Math.random() * 0.6);
  }
  this.rotation = (Math.PI * 2) * Math.random();
  this.rotationSpeed = (Math.PI * 2) * (Math.random() - 0.5) * 0.0005;
  this.color = randomColor();
}

while (pieces.length < numberOfPieces) {
  pieces.push(new Piece(Math.random() * canvas.width, Math.random() * canvas.height));
}
var bye = 0;

function myfunction() {
  var hello = Date.now();

  var difference = hello - bye;
  if (difference > 1000) {
    a = 0;
    numberOfPieces = pieces.length + 100;

    intervalID = setInterval(update, 30);
    draw();
    bye = Date.now();
  }

}
<canvas id="confetti"></canvas>
<button style="float: right; border: 1px blue solid; width: 100px; height: 100px;" onclick="myfunction()">Click me</button>

【问题讨论】:

  • 是的,它们是横向的。最初他们几乎喜欢直线下降。 1000 次点击后,横向移动增加。
  • 您的每一次按钮点击都会以自己的间隔开始一个新动画,而不是停止前一个动画。单击两次后,您将有两个动画间隔同时运行,它们同时执行两倍的更新次数。
  • 另外,为什么你有单独的更新和绘制循环?

标签: javascript html css canvas


【解决方案1】:

按重要性顺序修复:

  • 只运行一次您的引擎! (不是每次点击。PS:你没有清除间隔)
  • 删除setInterval,您已经将requestAnimationFrame() 用作引擎
  • 性能明智,创建一个 pieces = {} 对象(而不是数组),并在您的作品中创建存储 this.id(只是一个随机数)
  • 删除draw() 方法。而是创建一个this.draw() 方法 五彩纸屑
  • 将您的删除逻辑放入this.draw() 方法中。要从我们的 pieces 对象中删除该部分 - 只需使用 delete pieces[this.id]
  • 添加逻辑以从pieces 对象中删除一块 - 如果它超出了左/右画布边缘
  • 在您的引擎中,只需循环 pieces 并调用每个部分的 .draw() 方法。
  • 无需将参数传递给Piece 构造函数。保持简单,只需使用new Piece();
  • 创建一个可重用的 rnd(min, max) 函数以返回从 minmax 的浮点数(已排除)
  • 删除不必要的变量(如alastUpdateTime
  • 删除不必要的while 函数外初始化循环。
  • myfunction() 重命名为有意义的名称,即:createConfetti()
  • colors 数组放入“root” 范围内。这些是您的静态值。
  • 使用 Element.addEventListener() 而不是像 onclick 这样的内联 JavaScript。
  • 了解constlet 之间的区别并相应地使用。你不再需要var

示例如下:

const width1 = window.innerWidth || document.documentElement.clientWidth ||
  document.body.clientWidth;
const height1 = window.innerHeight || document.documentElement.clientHeight ||
  document.body.clientHeight;
const canvas = document.getElementById('confetti');
const ctx = canvas.getContext('2d');
const pieces = {}; // For better delete performance
const numberOfPieces = 100;
const colors = ['#999999', '#b7b7b7', '#D3D3D3', '#f48024', '#d9d9d9'];
const rnd = (min, max) => Math.random() * (max - min) + min;

let bye = 0;

canvas.width = width1;
canvas.height = height1;

function Piece() {
  this.id = rnd(0, 1e3);
  this.g = rnd(0.7, 2);
  this.w = rnd(5, 25);
  this.x = rnd(0, canvas.width);
  this.y = -this.w;
  this.dir = rnd(0, 1) > 0.5 ? rnd(0, 0.5) : -rnd(0, 0.5);
  this.r = rnd(1, 8);
  this.rSpeed = rnd(1, 5) * 0.01;
  this.color = colors[~~rnd(0, colors.length)];
  this.draw = () => {
    if (this.y > canvas.height || this.x < -this.w || this.x > canvas.width + this.w) {
      delete pieces[this.id];
      return;
    }
    this.y += this.g;
    this.r += this.rSpeed;
    this.x += this.dir;
    ctx.save();
    ctx.fillStyle = this.color;
    ctx.translate(this.x + this.w / 2, this.y + this.w / 2);
    ctx.rotate(this.r);
    ctx.fillRect(-this.w / 2, -this.w / 2, this.w, this.w);
    ctx.restore();
  }
  // populate into object
  pieces[this.id] = this;
}

function createConfetti() {
  const hi = Date.now();
  if (hi - bye <= 1000) return;
  bye = hi;
  // Populate pieces array
  let i = numberOfPieces;
  while (i) {
    new Piece();
    i--;
  }
}

function engine() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  const piecesIDs = Object.keys(pieces);
  if (piecesIDs.length) {
    piecesIDs.forEach(id => pieces[id].draw());
  }
  requestAnimationFrame(engine);
}

engine(); // Start engine once! Not on every click
document.querySelector('#createConfetti').addEventListener('click', createConfetti);
* { margin:0; }
button { z-index:1; position:absolute; }
#confetti { display:block; }
<button id="createConfetti">Click me</button>
<canvas id="confetti"></canvas>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2016-12-21
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多