Last active
August 29, 2015 14:06
-
-
Save garrows/db2364809237fa9cabd4 to your computer and use it in GitHub Desktop.
Window Pane Slider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Slider Test</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> | |
<style> | |
body { | |
margin: 0px; | |
padding: 0px; | |
} | |
.slider-wrapper { | |
position: relative; | |
width: 100%; | |
height: 100%; | |
overflow-x: hidden; | |
} | |
.slider { | |
position: relative; | |
height: 100%; | |
transform: translate3d(0px, 0px, 0px); | |
/*width: 300%; Calculated */ | |
} | |
.slider>div { | |
position: absolute; | |
padding: 0px; | |
/*width: 33%; Calculated */ | |
height: 100%; | |
overflow: auto; | |
overflow-scrolling: touch; | |
-webkit-overflow-scrolling: touch; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="slider-wrapper"> | |
<div class="slider"> | |
<div style="background-color:red">One</div> | |
<div style="background-color:green"> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
<p>paragraph</p> | |
</div> | |
<div style="background-color:blue">Three | |
<input type="range" name="points" min="0" max="10"> | |
</div> | |
</div> | |
</div> | |
<script> | |
//amount of pixels between touch samples to constitute a flick between panels | |
var FLICK_SPEED = 0; | |
var HORIZONTAL_ANGLE_THRESHOLD = 20; | |
var lastClickPosition = null; | |
var snapTimeout = null; | |
var swipingHorizontal = false; | |
var checkHorizontal = false; | |
var slider = null; | |
var forceSwipe = false; | |
var setupPositions = function() { | |
slider = document.querySelector('.slider'); | |
var panels = slider.children; | |
slider.style.width = (panels.length * 100) + '%'; | |
//calculate leftmost | |
var x = -window.innerWidth * ((panels.length - 1) / 2); | |
for (var i = 0; i < panels.length; i++) { | |
panels[i].style.WebkitTransform = 'translate3d(' + Math.round(x) + 'px, 0px, 0px)'; | |
panels[i].style.transform = 'translate3d(' + Math.round(x) + 'px, 0px, 0px)'; | |
panels[i].style.width = Math.round(slider.clientWidth / slider.children.length) + 'px'; | |
x += window.innerWidth; | |
} | |
}; | |
window.onload = setupPositions(); | |
window.onresize = setupPositions(); | |
// setupPositions(); | |
var convertClick = function(evt) { | |
//Handle click or touch. | |
var source = (evt.touches && evt.touches[0]) || evt; | |
return { | |
x: source.clientX, | |
y: source.clientY | |
}; | |
}; | |
var mouseMove = function(evt) { | |
if (evt.which !== 1 && !evt.touches) { | |
//console.log('resetting'); | |
// lastClickPosition = null; | |
return true; | |
} | |
var pos = convertClick(evt); | |
if (!lastClickPosition) { | |
lastClickPosition = pos; | |
checkHorizontal = true; | |
return true; | |
} | |
pos.dx = lastClickPosition.x - pos.x; | |
pos.dy = lastClickPosition.y - pos.y; | |
if (checkHorizontal) { | |
//Calculate angle of swipe | |
checkHorizontal = false; | |
var radians = Math.atan(pos.dy / pos.dx); | |
var degrees = radians * 180 / Math.PI; | |
if (degrees < HORIZONTAL_ANGLE_THRESHOLD && degrees > -HORIZONTAL_ANGLE_THRESHOLD) { | |
swipingHorizontal = true; | |
} | |
} | |
lastClickPosition = pos; | |
if (swipingHorizontal) { | |
evt.preventDefault(); | |
} else { | |
//Dont swipe because we are scrolling | |
return false; | |
} | |
x += pos.dx; | |
var t = slider.style.transform; | |
if (!t) { | |
t = 'translate3d(0px, 0px, 0px)'; | |
} | |
var x = parseInt(t.substring(t.indexOf('(') + 1, t.indexOf('px'))); | |
x -= pos.dx; | |
//Make sure it hasnt swiped too far | |
if (x > slider.clientWidth / (slider.children.length / 2) || x < -slider.clientWidth / (slider.children.length / 2)) { | |
return; | |
} | |
slider.style.WebkitTransform = 'translate3d(' + Math.round(x) + 'px, 0px, 0px)'; | |
slider.style.transform = 'translate3d(' + Math.round(x) + 'px, 0px, 0px)'; | |
return true; | |
}; | |
var mouseDown = function(evt) { | |
lastClickPosition = null; | |
}; | |
var mouseUp = function() { | |
if (swipingHorizontal == false) { | |
lastClickPosition = null; | |
return; | |
} | |
swipingHorizontal = false; | |
//Check for fast flick to force change of screens | |
if (lastClickPosition && (lastClickPosition.dx > FLICK_SPEED || lastClickPosition.dx < -FLICK_SPEED)) { | |
//Flick direction | |
if (lastClickPosition.dx > 0) { | |
//right | |
forceSwipe = -1; | |
} else { | |
//left | |
forceSwipe = 1; | |
} | |
} | |
lastClickPosition = null; | |
//get its position from the css transform | |
var t = slider.style.transform; | |
var x = parseInt(t.substring(t.indexOf('(') + 1, t.indexOf('px'))); | |
//Find the position it needs to snap to. | |
var closestTargetX = window.innerWidth * (Math.round(x / window.innerWidth)); | |
if (forceSwipe) { | |
//Make sure it hasnt swiped too far | |
if (closestTargetX + window.innerWidth * forceSwipe < slider.clientWidth / 2 && closestTargetX + window.innerWidth * forceSwipe > -slider.clientWidth / 2) { | |
//check if we arent over 50% swipe already | |
var distanceToTarget = closestTargetX - x; | |
var isUnderHalfWay = distanceToTarget * forceSwipe < 0; | |
if (isUnderHalfWay) { | |
closestTargetX += window.innerWidth * forceSwipe; | |
} | |
} | |
} | |
var animateToLocation = function() { | |
var moved = false; | |
var diff = x - closestTargetX; | |
//only move in 20% increments | |
var increment = -(diff * 0.2); | |
//Does it need to move | |
if (Math.round(increment) != 0) { | |
moved = true; | |
} else { | |
//last increment, just jump to the location to prevent rounding errors | |
increment = -diff; | |
} | |
x += increment; | |
slider.style.WebkitTransform = 'translate3d(' + Math.round(x) + 'px, 0px, 0px)' | |
slider.style.transform = 'translate3d(' + Math.round(x) + 'px, 0px, 0px)' | |
if (moved) { | |
requestAnimationFrame(animateToLocation); | |
} else { | |
forceSwipe = false; | |
} | |
}; | |
requestAnimationFrame(animateToLocation); | |
} | |
document.body.addEventListener("mousemove", mouseMove, false); | |
document.body.addEventListener("touchmove", mouseMove, false); | |
document.body.addEventListener("touchstart", mouseDown, false); | |
document.body.addEventListener("mousedown", mouseDown, false); | |
document.body.addEventListener("touchend", mouseUp, false); | |
document.body.addEventListener("mouseup", mouseUp, false); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment