每次我生成一个新粒子时,粒子速度(在 canvas 上)都会增加。是由于请求动画帧吗?

Speed of particle (on canvas) increases everytime I generate a new one. Is it due to requestanimationframe?

目的是使用 class 粒子创建粒子(在用户单击按钮时),一旦它成为 运行 应该的,让用户可以控制速度,重力和其他一些东西。问题是每次用户点击创建一个新的粒子时,速度都会增加。

我不确定为什么,但是当我在没有请求动画框架的情况下演示它时,它看起来像它应该的那样工作,但如果它没有动画就没用了。

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

const gravitySlider = document.getElementById('gravity-slider')
const output = document.getElementById('value')


//GENERIC PARTICLE CREATION

class particle{
    
    constructor(positionX, positionY, velocityX, velocityY, radius, color,){
    this.positionX = Math.max(radius, Math.min(1024 - radius, positionX))
    this.positionY = Math.min(768 - radius, positionY)
    this.velocityX = velocityX
    this.velocityY = velocityY
    this.radius = radius
    this.color = color
    }
    
update() {
    
    if (
      this.positionX > 1024 - this.radius || this.positionX < this.radius
    ) {
      this.velocityX *= -1
    }

    if (this.positionY >= 768 - this.radius || this.positionY < this.radius) {
      this.velocityY *= -1
    }

    this.velocityX *= 0.999
    this.velocityY += 1
    
    this.positionX += this.velocityX;
    this.positionY += this.velocityY;
    
    this.positionY = Math.min(768 - this.radius, this.positionY)
  }
    
    drawParticle() {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.positionX, this.positionY, this.radius, 0, Math.PI * 2);
    ctx.fill();
  }
}

//CREATE BUTTON INTERACTIVITY AND CLICK COUNTING VARIABLE

const newParticleButton = document.getElementById('new-particle-button')
newParticleButton.onclick = drawNewParticle

//Even listener for click counting

let clickCount = 0
 
const clickCounter = document.querySelector('#new-particle-button')
clickCounter.addEventListener('click' ,function(event){
    clickCount+= 1 })

const particleArray = []

//DRAW NEW PARTICLES ON BUTTON PRESS

function drawNewParticle(){

    //Generate particle and add to array of particles

    generateParticle = particleArray.push (new particle(
    Math.random() * 1014,
    Math.random() * 758,
    1,
    1,
    10,
    'hsla(0, 0%, 0%, 1)'
    )
    )

    // clear canvas
    
    ctx.clearRect(0, 0, 1024, 768)
    
    
    for(i=0; i< clickCount; i++){
    particleArray[i].update()
    particleArray[i].drawParticle()
    
    }
    
        requestAnimationFrame(drawNewParticle)
}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Canvas Basics</title>
    <link rel="stylesheet" href="styles/index.css">
    <script src="scripts/canvas.js" defer></script>
  </head>
  <body>
    
     <canvas id="canvas" width="1024" height="768" style="border: 1px dashed">
      Canvas is not supported
    </canvas>
      
     <button class="new-particle-button" id="new-particle-button">NEW PARTICLE</button>
     <div class="slidecontainer">
        <label for="gravity-slider">GRAVITY</label>
        <input type="range" min="0" max="10" value="0" class="slider" id="gravity-slider">
         <p>Value: <span id="value"></span></p>
     </div>
      
    </body>
</html>

我会检查一下你是否经常 运行 drawNewParticle 作为你的动画函数,我会把这个(你的粒子创建函数):

particleArray.push (new particle(
    Math.random() * 1014,
    Math.random() * 758,
    1,
    1,
    10,
    'hsla(0, 0%, 0%, 1)'
    )
    );

在按钮的事件侦听器下,因为看起来您正在屏幕上创建一个粒子数组,每帧都会获得一个新项目。

如果这没有帮助,我很抱歉,也许我只是没有正确理解您的代码:\

您将要将动画循环与添加粒子函数分开。您需要在动画功能中做的就是清除 canvas 并更新和绘制对象。添加到数组应该是一个单独的函数。每次单击按钮时,都会再次调用 requestAnimationFrame,从而编译其效果。

function drawNewParticle(){
    //Generate particle and add to array of particles
    generateParticle = particleArray.push (new particle(
    Math.random() * 1014,
    Math.random() * 758,
    1,
    1,
    10,
    'hsla(0, 0%, 0%, 1)'
    )
    )
}    

function animate() {
    ctx.clearRect(0, 0, 1024, 768)
       
    for(i=0; i< clickCount; i++){
    particleArray[i].update()
    particleArray[i].drawParticle() 
    }   
    requestAnimationFrame(animate)
}
animate();