diff options
Diffstat (limited to 'bounds2/demo.js')
-rw-r--r-- | bounds2/demo.js | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/bounds2/demo.js b/bounds2/demo.js new file mode 100644 index 0000000..8f3e1d4 --- /dev/null +++ b/bounds2/demo.js @@ -0,0 +1,125 @@ +/*global Particle: false, Attractor: false, rAF: false */ + +var canvas, ctx; +var canvasW, canvasH; +var particle; +var attractors = []; +var maxDistance; + +document.addEventListener( 'DOMContentLoaded', init, false ); + +function init() { + canvas = document.querySelector('canvas'); + ctx = canvas.getContext('2d'); + // set size + canvasW = canvas.width = window.innerWidth - 20; + canvasH = canvas.height = window.innerHeight - 80; + + + canvas.addEventListener( 'mousedown', onMousedown, false ); + + particle = new Particle( canvasW / 2, canvasH / 2 ); + var x0 = canvasW * 0.2; + var x1 = canvasW * 0.8; + attractors.push( new Attractor( x0, canvasH / 2 ) ); + attractors.push( new Attractor( x1, canvasH / 2 ) ); + maxDistance = Math.abs( x1 - x0 ) *0.5; + + animate(); +} + +// -------------------------- animate, render, update -------------------------- // + + +function animate() { + // apply force of bounds to particle + if ( !isDragging ) { + // left bound + applyBoundForce( attractors[0].x, 1 ); + // right bound + applyBoundForce( attractors[1].x, -1 ); + } + + particle.update(); + + render(); + rAF( animate ); +} + +function applyBoundForce( boundX, direction ) { + // left force + var distance = boundX - particle.x; + var force = distance * 0.05; + force = Math.max( force * direction, 0 ) * direction; + // prevent particle from bounds too far back + // don't apply force if particle is returning from outside bounds + if ( force && particle.velocity * direction > 0 ) { + // resting position + var restPosition = particle.getRestingPosition(); + if ( restPosition.x * direction > boundX * direction ) { + force = ( boundX - particle.x ) / restPosition.frictionSum - particle.velocity; + } + } + particle.applyForce( force ); +} + + +function render() { + ctx.clearRect( 0, 0, canvasW, canvasH ); + + // render particle + ctx.fillStyle = 'hsla(0, 100%, 50%, 0.5)'; + circle( particle.x, particle.y, 15 ); + + // render attractor + ctx.fillStyle = 'hsla(240, 100%, 50%, 0.5)'; + for ( var i=0, len = attractors.length; i < len; i++ ) { + var attractor = attractors[i]; + circle( attractor.x, attractor.y, 8 ); + } +} + +function circle( x, y, radius ) { + ctx.beginPath(); + ctx.arc( x, y, radius, 0, Math.PI * 2, true ); + ctx.fill(); + ctx.closePath(); +} + +// -------------------------- mouse -------------------------- // + +var isDragging = false; + +function onMousedown( event ) { + event.preventDefault(); + isDragging = true; + window.addEventListener( 'mousemove', onMousemove, false ); + window.addEventListener( 'mouseup', onMouseup, false ); + particle.x = event.pageX; + particle.velocity = 0; +} + +var previousX; +var previousTime; +var currentTime; + +function onMousemove( event ) { + // previous + previousX = particle.x; + previousTime = currentTime; + // current + particle.x = event.pageX; + currentTime = new Date(); +} + +function onMouseup( event ) { + if ( previousX ) { + particle.velocity = ( particle.x - previousX ) / ( currentTime - previousTime ); + particle.velocity *= 17; + previousX = null; + } + // console.log( particle.velocity ); + isDragging = false; + window.removeEventListener( 'mousemove', onMousemove, false ); + window.removeEventListener( 'mousemove', onMouseup, false ); +} |