100 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			100 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Particle Sim
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								## Particle Simulation in Canvas
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In this guide, we're going to build a basic particle simulation in Canvas using simple principles of animation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We will want to set up an array of particles with accelerations and velocities. We will create 100 particles at random points on the canvas.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								canvas = document.getElementById("canvas");
							 | 
						||
| 
								 | 
							
								ctx = canvas.getContext('2d');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var particles = [];
							 | 
						||
| 
								 | 
							
								for(var i=0; i<100; i++) {
							 | 
						||
| 
								 | 
							
								  particles.push(
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      x:Math.random()*canvas.width,
							 | 
						||
| 
								 | 
							
								      y:Math.random()*canvas.height,
							 | 
						||
| 
								 | 
							
								      vx:0,
							 | 
						||
| 
								 | 
							
								      vy:0,
							 | 
						||
| 
								 | 
							
								      ax:0,
							 | 
						||
| 
								 | 
							
								      ay:0
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In our draw loop, we render these particles.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								function draw() {
							 | 
						||
| 
								 | 
							
								  ctx.clearRect(0, 0, canvas.width, canvas.height);
							 | 
						||
| 
								 | 
							
								  for(var i=0; i<particles.length; i++) {
							 | 
						||
| 
								 | 
							
								    // update state
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // render state
							 | 
						||
| 
								 | 
							
								    ctx.beginPath();
							 | 
						||
| 
								 | 
							
								    ctx.arc(particles[i].x, particles[i].y, 5, 0, 2*Math.PI);
							 | 
						||
| 
								 | 
							
								    ctx.fill();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  window.requestAnimationFrame(draw);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								window.requestAnimationFrame(draw);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Now, all we need to do is update velocity and acceleration each frame. We will add the acceleration to the velocity and add the velocity to the position.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								function draw() {
							 | 
						||
| 
								 | 
							
								  for(var i=0; i<particles.length; i++) {
							 | 
						||
| 
								 | 
							
								    // update state
							 | 
						||
| 
								 | 
							
								    particles[i].x+=particles[i].vx;
							 | 
						||
| 
								 | 
							
								    particles[i].y+=particles[i].vy;
							 | 
						||
| 
								 | 
							
								    particles[i].vx+=particles[i].ax;
							 | 
						||
| 
								 | 
							
								    particles[i].vy+=particles[i].ay;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								    /* render code */
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  window.requestAnimationFrame(draw);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								window.requestAnimationFrame(draw);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								That's it! All we need to do to is create a force somewhere. Let's do it with a click listener.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```js
							 | 
						||
| 
								 | 
							
								canvas.addEventListener("click", function(e) {
							 | 
						||
| 
								 | 
							
								  var clickX = e.clientX-canvas.offsetLeft;
							 | 
						||
| 
								 | 
							
								  var clickY = e.clientY-canvas.offsetTop;
							 | 
						||
| 
								 | 
							
								  for(var i=0; i<particles.length; i++) {
							 | 
						||
| 
								 | 
							
								    var delx = particles[i].x-clickX;
							 | 
						||
| 
								 | 
							
								    var dely = particles[i].y-clickY;
							 | 
						||
| 
								 | 
							
								    var magnitudeSquared = Math.pow(delx, 2)+Math.pow(dely, 2);
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    particles[i].ax = 0.1*delx/magnitudeSquared;
							 | 
						||
| 
								 | 
							
								    particles[i].ay = 0.1*dely/magnitudeSquared;
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This adds force via the inverse-square law. See [this page](#placeholder) for more details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								That's all! The final codepen:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<p data-height="265" data-theme-id="0" data-slug-hash="OjMbpm" data-default-tab="js,result" data-user="alanluo" data-embed-version="2" data-pen-title="Particle Sim (FCC)" class="codepen">See the Pen <a href="https://codepen.io/alanluo/pen/OjMbpm/">Particle Sim (FCC)</a> by Alan Luo (<a href="https://codepen.io/alanluo">@alanluo</a>) on <a href="https://codepen.io">CodePen</a>.</p>
							 | 
						||
| 
								 | 
							
								<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								<!-- TODO: make it cooler! -->
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### More Information:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								- [MDN Canvas API](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |