diff options
author | David DeSandro <desandrocodes@gmail.com> | 2014-12-12 14:52:28 -0500 |
---|---|---|
committer | David DeSandro <desandrocodes@gmail.com> | 2014-12-12 14:52:28 -0500 |
commit | 4d8c5d58b78de0b222761a7961a179960458dd59 (patch) | |
tree | 1fc9f48539fe62a7c9d2f00438566b7b869b2457 | |
parent | 31545d7aa0241c7e86cb6e554b4f62799cd0959b (diff) | |
download | flickity-dev-4d8c5d58b78de0b222761a7961a179960458dd59.zip flickity-dev-4d8c5d58b78de0b222761a7961a179960458dd59.tar.gz flickity-dev-4d8c5d58b78de0b222761a7961a179960458dd59.tar.bz2 |
bounds3 demo
-rw-r--r-- | sandbox/bounds2/demo.js | 2 | ||||
-rw-r--r-- | sandbox/bounds3/demo.js | 188 | ||||
-rw-r--r-- | sandbox/bounds3/index.html | 26 | ||||
-rw-r--r-- | sandbox/bounds3/slider.js | 45 |
4 files changed, 260 insertions, 1 deletions
diff --git a/sandbox/bounds2/demo.js b/sandbox/bounds2/demo.js index 763445f..8f3e1d4 100644 --- a/sandbox/bounds2/demo.js +++ b/sandbox/bounds2/demo.js @@ -49,7 +49,7 @@ function animate() { function applyBoundForce( boundX, direction ) { // left force var distance = boundX - particle.x; - var force = distance * 0.03; + 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 diff --git a/sandbox/bounds3/demo.js b/sandbox/bounds3/demo.js new file mode 100644 index 0000000..f245b06 --- /dev/null +++ b/sandbox/bounds3/demo.js @@ -0,0 +1,188 @@ +/*global Slider: false, rAF: false */ + +// -------------------------- demo -------------------------- // + +var canvas, ctx; +var canvasW, canvasH; +var slider; +var cells = []; +var leftBound, rightBound; +var cellWidths = [ 0.2, 0.2, 0.4, 0.2, 0.3 ]; + +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 cellX = 0; + var gutter = 40; + for ( var i=0, len = cellWidths.length; i < len; i++ ) { + var cellWidth = cellWidths[i]; + var cell = { + width: canvasW * cellWidth, + height: canvasH - 40, + x: cellX, + index: i + }; + cellX += cell.width + gutter; + cells.push( cell ); + } + + leftBound = 100; + rightBound = canvasW - 100; + + canvas.addEventListener( 'mousedown', onMousedown, false ); + + slider = new Slider( leftBound, 0 ); + slider.width = cellX - gutter; + + animate(); +} + +// -------------------------- animate -------------------------- // + +function animate() { + if ( !isDragging ) { + applyLeftBoundForce(); + applyRightBoundForce(); + } + + slider.update(); + + render(); + rAF( animate ); +} + +function applyLeftBoundForce() { + var sliderX = slider.x; + + var distance = leftBound - sliderX; + var force = distance * 0.05; + force = Math.min( force, 0 ); + // prevent slider from bounds too far back + // don't apply force if slider is returning from outside bounds + if ( force && slider.velocity < 0 ) { + // resting position + var restPosition = slider.getRestingPosition(); + if ( restPosition.x < leftBound ) { + force = ( leftBound - slider.x ) / restPosition.frictionSum - slider.velocity; + } + } + slider.applyForce( force ); +} + +function applyRightBoundForce() { + var sliderX = slider.x + slider.width; + + var distance = rightBound - sliderX; + var force = distance * 0.05; + force = Math.max( force, 0 ); + // prevent slider from bounds too far back + // don't apply force if slider is returning from outside bounds + if ( force && slider.velocity > 0 ) { + // resting position + var restPosition = slider.getRestingPosition(); + if ( restPosition.x + slider.width > rightBound ) { + force = ( rightBound - sliderX ) / restPosition.frictionSum - slider.velocity; + } + } + slider.applyForce( force ); +} + +// -------------------------- render -------------------------- // + +function render() { + ctx.clearRect( 0, 0, canvasW, canvasH ); + + // bounds + ctx.lineWidth = 1; + ctx.strokeStyle = 'hsla(300, 100%, 40%, 1)'; + line( leftBound, 0, leftBound, canvasH ); + line( rightBound, 0, rightBound, canvasH ); + + // cells + ctx.save(); + ctx.translate( slider.x, 0 ); + for ( var i=0, len = cells.length; i < len; i++ ) { + var cell = cells[i]; + var hue = i * 70; + ctx.fillStyle = 'hsla(' + hue + ', 100%, 40%, 0.5)'; + ctx.fillRect( cell.x, 20, cell.width, cell.height ); + // target line + ctx.strokeStyle = 'yellow'; + line( cell.target, 40, cell.target, cell.height ); + } + + ctx.restore(); +} + +function line( x1, y1, x2, y2 ) { + ctx.beginPath(); + ctx.moveTo( x1, y1 ); + ctx.lineTo( x2, y2 ); + ctx.stroke(); + ctx.closePath(); +} + +function circle( x, y, radius ) { + ctx.beginPath(); + ctx.arc( x, y, radius, 0, Math.PI * 2 ); + ctx.fill(); + 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(); + window.removeEventListener( 'mousemove', onMousemove, false ); + window.removeEventListener( 'mousemove', onMouseup, false ); +} + +function dragEnd() { + if ( previousX ) { + // set slider velocity + slider.velocity = ( slider.x - previousX ) / ( currentTime - previousTime ); + slider.velocity *= 1000 / 60; + // reset previousX + previousX = null; + } else { + estimateX = slider.x; + } + + isDragging = false; + +} diff --git a/sandbox/bounds3/index.html b/sandbox/bounds3/index.html new file mode 100644 index 0000000..c6b6e54 --- /dev/null +++ b/sandbox/bounds3/index.html @@ -0,0 +1,26 @@ +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + + <title>bounds3</title> + + <style> + * { margin: 0; padding: 0; } + </style> + +</head> +<body> + + <h1>bounds3</h1> + +<canvas></canvas> + +<p></p> + +<script src="../request-animation-frame.js"></script> +<script src="slider.js"></script> +<script src="demo.js"></script> + +</body> +</html> diff --git a/sandbox/bounds3/slider.js b/sandbox/bounds3/slider.js new file mode 100644 index 0000000..e245071 --- /dev/null +++ b/sandbox/bounds3/slider.js @@ -0,0 +1,45 @@ +( function() { + +function Slider( x, y ) { + this.x = x; + this.y = y; + this.velocity = 0; + this.accel = 0; + this.friction = 0.15; +} + +Slider.prototype.update = function() { + this.velocity += this.accel; + this.velocity *= ( 1 - this.friction ); + this.x += this.velocity; + this.accel = 0; +}; + +Slider.prototype.applyForce = function( force ) { + this.accel += force; +}; + + +Slider.prototype.getRestingPosition = function() { + + var fFriction = 1 - this.friction; + var restingVelo = 0.07; + var ticks = getBaseLog( fFriction, restingVelo / Math.abs( this.velocity ) ); + var frictionSum = ( Math.pow( fFriction, ticks + 1 ) - 1 ) / ( fFriction - 1 ); + var restX = this.x + this.velocity * fFriction * frictionSum; + + return { + x: restX, + frictionSum: frictionSum + }; +}; + + +function getBaseLog( a, b ) { + return Math.log( b ) / Math.log( a ); +} + + +window.Slider = Slider; + +})(); |