├── style.css ├── readme.md ├── index.html └── particles.js /style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin:0; 4 | padding:0; 5 | } 6 | 7 | canvas { 8 | background-color: #000; 9 | } 10 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # JS Particles 2 | 3 | ## Example 4 | 5 | - [http://orangespaceman.github.io/js-particles](http://orangespaceman.github.io/js-particles) 6 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | JS Particles 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /particles.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Particles 3 | */ 4 | (function () { 5 | 6 | "use strict"; 7 | 8 | /* 9 | * global variables 10 | */ 11 | var 12 | // HTML canvas element 13 | canvas, 14 | 15 | // canvas draw context 16 | ctx, 17 | 18 | // collection of existing particles 19 | particles = [], 20 | 21 | // configurable options 22 | config = { 23 | 24 | // number of particles to draw 25 | particleCount : 50, 26 | 27 | // minimum distance for each particle to affect another 28 | minimumAffectingDistance : 50 29 | }; 30 | 31 | /* 32 | * init 33 | */ 34 | function init () { 35 | drawCanvas(); 36 | createParticles(); 37 | loop(); 38 | 39 | // resize canvas on page resize 40 | window.addEventListener("resize", function (event) { 41 | drawCanvas(); 42 | }); 43 | } 44 | 45 | 46 | /* 47 | * start redraw loop logic 48 | */ 49 | function loop () { 50 | clear(); 51 | update(); 52 | draw(); 53 | queue(); 54 | } 55 | 56 | /* 57 | * wipe canvas ready for next redraw 58 | */ 59 | function clear () { 60 | ctx.clearRect(0, 0, canvas.width, canvas.height); 61 | } 62 | 63 | /* 64 | * update particle positions 65 | */ 66 | function update () { 67 | 68 | // update each particle's position 69 | for (var count = 0; count < particles.length; count++) { 70 | 71 | var p = particles[count]; 72 | 73 | // Change the velocities 74 | p.x += p.vx; 75 | p.y += p.vy; 76 | 77 | // Bounce a particle that hits the edge 78 | if(p.x + p.radius > canvas.width || p.x - p.radius < 0) { 79 | p.vx = -p.vx; 80 | } 81 | 82 | if(p.y + p.radius > canvas.height || p.y - p.radius < 0) { 83 | p.vy = -p.vy; 84 | } 85 | 86 | // Check particle attraction 87 | for (var next = count + 1; next < particles.length; next++) { 88 | var p2 = particles[next]; 89 | calculateDistanceBetweenParticles(p, p2); 90 | } 91 | } 92 | } 93 | 94 | /* 95 | * update visual state - draw each particle 96 | */ 97 | function draw () { 98 | for (var count = 0; count < particles.length; count++) { 99 | var p = particles[count]; 100 | p.draw(); 101 | } 102 | } 103 | 104 | /* 105 | * prepare next redraw when the browser is ready 106 | */ 107 | function queue () { 108 | window.requestAnimationFrame(loop); 109 | } 110 | 111 | // go! 112 | init(); 113 | 114 | 115 | /* 116 | * Objects 117 | */ 118 | 119 | /* 120 | * Particle 121 | */ 122 | function Particle () { 123 | 124 | // Position particle 125 | this.x = Math.random() * canvas.width; 126 | this.y = Math.random() * canvas.height; 127 | 128 | // Give particle velocity, between -1 and 1 129 | this.vx = -1 + Math.random() * 2; 130 | this.vy = -1 + Math.random() * 2; 131 | 132 | // Give particle a radius 133 | this.radius = 4; 134 | 135 | // draw particle 136 | this.draw = function () { 137 | ctx.fillStyle = "white"; 138 | ctx.beginPath(); 139 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); 140 | ctx.fill(); 141 | } 142 | } 143 | 144 | /* 145 | * Draw canvas 146 | */ 147 | function drawCanvas () { 148 | canvas = document.querySelector("canvas"); 149 | ctx = canvas.getContext("2d"); 150 | 151 | // set canvas to full page dimensions 152 | canvas.width = window.innerWidth; 153 | canvas.height = window.innerHeight; 154 | } 155 | 156 | /* 157 | * Create particles 158 | */ 159 | function createParticles () { 160 | for(var i = 0; i < config.particleCount; i++) { 161 | particles.push(new Particle()); 162 | } 163 | } 164 | 165 | 166 | /* 167 | * Distance calculator between two particles 168 | */ 169 | function calculateDistanceBetweenParticles (p1, p2) { 170 | 171 | var dist, 172 | dx = p1.x - p2.x, 173 | dy = p1.y - p2.y; 174 | 175 | dist = Math.sqrt(dx*dx + dy*dy); 176 | 177 | // Check whether distance is smaller than the min distance 178 | if(dist <= config.minimumAffectingDistance) { 179 | 180 | // set line opacity 181 | var opacity = 1 - dist/config.minimumAffectingDistance; 182 | 183 | // Draw connecting line 184 | ctx.beginPath(); 185 | ctx.strokeStyle = "rgba(255, 255, 255, " + opacity +")"; 186 | ctx.moveTo(p1.x, p1.y); 187 | ctx.lineTo(p2.x, p2.y); 188 | ctx.stroke(); 189 | ctx.closePath(); 190 | 191 | // Calculate particle acceleration 192 | var ax = dx / 2000, 193 | ay = dy / 2000; 194 | 195 | // Apply particle acceleration 196 | p1.vx -= ax; 197 | p1.vy -= ay; 198 | 199 | p2.vx += ax; 200 | p2.vy += ay; 201 | } 202 | } 203 | })(); 204 | --------------------------------------------------------------------------------