Momentum

HTML
CSS
html { overflow: hidden; touch-action: none; content-zooming: none; } body { position: absolute; margin: 0; padding: 0; width: 100%; height: 100%; background: #222; } canvas { position: absolute; background: #000; width: 100%; height: 100%; }
JAVASCRIPT
/* * fluid JS * ge1doot - 1 May 2011 * -------------------- * adapted from http://violentcoding.com/blog/2008/07/26/archivhtml { overflow: hidden; touch-action: none; content-zooming: none; } body { position: absolute; margin: 0; padding: 0; width: 100%; height: 100%; background: #222; } canvas { position: absolute; background: #000; width: 100%; height: 100%; }es/135 (dead link) * ref: http://www.cs.ubc.ca/~rbridson/fluidsimulation/ */ ~ function() { 'use strict'; var pmX = 0, pmY = 0, nbX, nbY, grid = [], particles = []; //////////////// var res = 20, nbP = 1000, psi = 50; //////////////// // ----- Particle ----- var Particle = function(x, y) { this.x = this.px = x; this.y = this.py = y; this.xvel = 0; this.yvel = 0; this.next = true; }; Particle.prototype.update = function() { if (this.x > 0 && this.x < canvas.width && this.y > 0 && this.y < canvas.height) { var x = (0.5 + this.x / res) | 0; var y = (0.5 + this.y / res) | 0; if (x >= nbX) x = nbX - 1; if (y >= nbY) y = nbY - 1; // ----- apply grid ----- var cell = grid[y * nbX + x]; var ax = (this.x % res) / res; var ay = (this.y % res) / res; this.xvel += (1 - ax) * cell.xvel * 0.05 + ax * cell.R.xvel * 0.05 + ay * cell.B.xvel * 0.05; this.yvel += (1 - ay) * cell.yvel * 0.05 + ax * cell.R.yvel * 0.05 + ay * cell.B.yvel * 0.05; this.x += this.xvel; this.y += this.yvel - 0.5; // ----- canvas painting ----- var speed = (0.5 + this.xvel + this.yvel) | 0; ctx.lineWidth = speed * 0.8 + 2; ctx.lineCap = "round"; ctx.beginPath(); ctx.moveTo((0.5 + this.x) | 0, (0.5 + this.y) | 0); ctx.lineTo((0.5 + this.px) | 0, (1.5 + this.py) | 0); ctx.strokeStyle = "rgba(" + (speed * 25) + "," + 255 + "," + (speed * 25) + ", 1)"; ctx.stroke(); this.px = this.x; this.py = this.y; } else { // ----- new particle ----- this.x = this.px = Math.random() * canvas.width; this.y = this.py = Math.random() * canvas.height; this.xvel = 0; this.yvel = 0; } this.xvel *= 0.5; this.yvel *= 0.5; // ---- fast loop ---- return this.next; }; // ----- Grid ----- var Grid = function(x, y) { this.x = x; this.y = y; this.xvel = 0; this.yvel = 0; this.pressure = 0; this.L = new nullGrid(); this.B = new nullGrid(); this.T = new nullGrid(); this.R = new nullGrid(); this.TL = new nullGrid(); this.TR = new nullGrid(); this.BL = new nullGrid(); this.BR = new nullGrid(); this.next = true; }; var nullGrid = function() { this.x = 0; this.y = 0; this.xvel = 0; this.yvel = 0; this.pressure = 0; }; Grid.prototype.update = function() { //----- pointer ------ var dx = this.x - pointer.x; var dy = this.y - pointer.y; var dist = Math.sqrt(dy * dy + dx * dx); if (dist < psi) { if (dist < 8) dist = psi; var p = psi / dist; this.xvel += (pointer.x - pmX) * p; this.yvel += (pointer.y - pmY) * p; } // ----- pressure ----- this.pressure = ( this.TL.xvel * 0.5 + this.L.xvel + this.BL.xvel * 0.5 - this.TR.xvel * 0.5 - this.R.xvel - this.BR.xvel * 0.5 + this.TL.yvel * 0.5 + this.T.yvel + this.TR.yvel * 0.5 - this.BL.yvel * 0.5 - this.B.yvel - this.BR.yvel * 0.5 ) * 0.25; // ----- velocity ----- this.xvel += (this.TL.pressure * 0.5 + this.L.pressure + this.BL.pressure * 0.5 - this.TR.pressure * 0.5 - this.R.pressure - this.BR.pressure * 0.5) * 0.25; this.yvel += (this.TL.pressure * 0.5 + this.T.pressure + this.TR.pressure * 0.5 - this.BL.pressure * 0.5 - this.B.pressure - this.BR.pressure * 0.5) * 0.25; this.xvel *= 0.996; this.yvel *= 0.996; return this.next; }; // ----- create grid ----- var createGrid = function() { grid = []; particles = []; // ----- create grid ----- for (var y = 0; y < nbY; y++) { for (var x = 0; x < nbX; x++) { grid[y * nbX + x] = new Grid(x * res, y * res); } } grid[grid.length - 1].next = false; // ----- link surrounding cells ----- for (var x = 0; x < nbX; x++) { for (var y = 0; y < nbY; y++) { var cell = grid[y * nbX + x]; if (y > 0) { var T = grid[(y - 1) * nbX + x]; cell.T = T; T.B = cell; } if (x > 0) { var L = grid[y * nbX + x - 1]; cell.L = L; L.R = cell; } if (y > 0 && x > 0) { var TL = grid[(y - 1) * nbX + x - 1]; cell.TL = TL; TL.BR = cell; } if (y > 0 && x < nbX - 1) { var TR = grid[(y - 1) * nbX + x + 1]; cell.TR = TR; TR.BL = cell; } } } // ---- create particles ----- for (var i = 0; i < nbP; i++) { particles.push(new Particle( Math.random() * canvas.width, Math.random() * canvas.height )); } particles[particles.length - 1].next = false; } // ---- main loop ---- var run = function() { requestAnimationFrame(run); ctx.fillStyle = "rgba(0,0,0,0.04)"; ctx.fillRect(0, 0, canvas.width, canvas.height); for ( var i = 0; grid[i++].update(); ); for ( var i = 0; particles[i++].update(); ); pmX = pointer.x; pmY = pointer.y; }; // ---- set canvas ---- var canvas = { width: 0, height: 0, elem: document.createElement('canvas'), resize: function() { var o = this.elem; var w = this.elem.offsetWidth * 1; var h = this.elem.offsetHeight * 1; if (w !== this.width || h !== this.height) { for (this.left = 0, this.top = 0; o !== null; o = o.offsetParent) { this.left += o.offsetLeft; this.top += o.offsetTop; } this.width = this.elem.width = w; this.height = this.elem.height = h; nbX = Math.round(w / res); nbY = Math.round(h / res); createGrid(); } }, init: function() { var ctx = this.elem.getContext('2d'); document.body.appendChild(this.elem); window.addEventListener('resize', this.resize.bind(this), false); this.resize(); return ctx; } }; var ctx = canvas.init(); // ---- pointer ---- var pointer = (function(canvas) { var pointer = { x: canvas.width * 0.5, y: canvas.height * 0.5, canvas: canvas, pointer: function(e) { var touchMode = e.targetTouches, pointer; if (touchMode) { e.preventDefault(); pointer = touchMode[0]; } else pointer = e; this.x = pointer.clientX - this.canvas.left; this.y = pointer.clientY - this.canvas.top; }, }; window.addEventListener('mousemove', function(e) { this.pointer(e); }.bind(pointer), false); window.addEventListener('touchmove', function(e) { this.pointer(e); }.bind(pointer), false); return pointer; }(canvas)); // ----- start ----- run(); }();
Expand for more options Login