diff options
Diffstat (limited to 'cells1/demo.js')
-rw-r--r-- | cells1/demo.js | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/cells1/demo.js b/cells1/demo.js new file mode 100644 index 0000000..80a8e2d --- /dev/null +++ b/cells1/demo.js @@ -0,0 +1,188 @@ +/*global Cell: false, Slider: false, rAF: false */ + +// -------------------------- demo -------------------------- // + +var canvas, ctx; +var canvasW, canvasH; +var slider; +var cells = []; +var estimateX = 0; +var selectedIndex = 0; + +var activeAttractor; +var activeAttractorIndex = 1; + +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 = 300; + + // create cells + var cellWidth = canvasW / 3; + for ( var i=0; i < 5; i++ ) { + var cell = new Cell({ + width: cellWidth, + height: canvasH - 40, + x: ( cellWidth + 40 ) * i, + index: i + }); + cells.push( cell ); + } + + canvas.addEventListener( 'mousedown', onMousedown, false ); + + slider = new Slider(); + + + animate(); +} + +// -------------------------- animate -------------------------- // + +function animate() { + if ( !isDragging ) { + slider.applyForce( getAttraction() ); + } + + slider.update(); + + render(); + rAF( animate ); +} + +function getAttraction() { + var cell = cells[ selectedIndex ]; + var attractorX = cell.x + cell.width / 2; + var distance = -attractorX - slider.x; + var force = distance * 0.03; + return force; +} + +// -------------------------- render -------------------------- // + +function render() { + ctx.clearRect( 0, 0, canvasW, canvasH ); + + // cursor + var cursorX = canvasW / 2; + ctx.lineWidth = 1; + ctx.strokeStyle = 'hsla(300, 100%, 40%, 1)'; + ctx.beginPath(); + ctx.moveTo( cursorX, 0 ); + ctx.lineTo( cursorX , canvasH ); + ctx.stroke(); + ctx.closePath(); + + // cells + ctx.save(); + ctx.translate( slider.x + cursorX, 0 ); + for ( var i=0, len = cells.length; i < len; i++ ) { + var cell = cells[i]; + ctx.fillStyle = 'hsla(0, 100%, 50%, 0.5)'; + ctx.fillRect( cell.x, 20, cell.width, cell.height ); + // target line + var cellTargetX = cell.x + cell.width / 2; + ctx.strokeStyle = 'yellow'; + line( cellTargetX, 40, cellTargetX, cell.height ); + } + + ctx.restore(); +} + +function line( x1, y1, x2, y2 ) { + ctx.beginPath(); + ctx.moveTo( x1, y1 ); + ctx.lineTo( x2, y2 ); + ctx.stroke(); + ctx.closePath(); +} + +// -------------------------- mouse -------------------------- // + +var isDragging = false; + +var dragStartX; + +function onMousedown( event ) { + event.preventDefault(); + isDragging = true; + window.addEventListener( 'mousemove', onMousemove, false ); + window.addEventListener( 'mouseup', onMouseup, false ); + dragStartX = event.pageX; + slider.dragStartX = slider.x; + slider.velocity = 0; +} + +var previousX; +var previousTime; +var currentTime; + +function onMousemove( event ) { + // previous + previousX = slider.x; + previousTime = currentTime; + // current + var moveX = event.pageX - dragStartX; + slider.x = slider.dragStartX + moveX; + currentTime = new Date(); +} + +function onMouseup( event ) { + dragEnd(); + // console.log( particle.velocity ); + window.removeEventListener( 'mousemove', onMousemove, false ); + window.removeEventListener( 'mousemove', onMouseup, false ); +} + +function dragEnd() { + if ( previousX ) { + // set particle velocity + slider.velocity = ( slider.x - previousX ) / ( currentTime - previousTime ); + slider.velocity *= 1000 / 60; + estimateX = slider.getRestingPosition(); + // reset previousX + previousX = null; + } else { + estimateX = slider.x; + } + + // remember this for checking later + var prevIndex = selectedIndex; + + // get closest attractor to end position + var minDistance = Infinity; + var targetX, distance; + for ( var i=0, len = cells.length; i < len; i++ ) { + var cell = cells[i]; + targetX = cell.x + cell.width / 2; + distance = Math.abs( -estimateX - targetX ); + if ( distance < minDistance ) { + selectedIndex = i; + minDistance = distance; + } + } + + // if not enough velocity to escape current attractor + // boost it + if ( selectedIndex === prevIndex ) { + var selectedCell = cells[ selectedIndex ]; + targetX = selectedCell.x + selectedCell.width / 2; + distance = -slider.x - targetX; + // console.log( ~~distance, ~~slider.velocity ); + if ( distance > 0 && slider.velocity < -1 && cells[ selectedIndex + 1 ] ) { + // if moving towards the right, and positive velocity, and the next attractor + selectedIndex++; + } else if ( distance < 0 && slider.velocity > 1 && cells[ selectedIndex - 1 ] ) { + // if moving towards the left, and negative velocity, and previous attractor + selectedIndex--; + } + } + + + isDragging = false; + +} |