Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active November 22, 2016 09:14
Show Gist options
  • Save mbostock/8411383 to your computer and use it in GitHub Desktop.
Save mbostock/8411383 to your computer and use it in GitHub Desktop.
Page Swiping
license: gpl-3.0
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
<style>
body {
background: #ccc;
margin: 0;
}
.page {
text-align: center;
top: 0;
width: 100%;
}
.page--light {
background: -moz-radial-gradient(center, ellipse cover, #fff 0%, #7db9e8 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #fff), color-stop(100%, #7db9e8));
background: -webkit-radial-gradient(center, ellipse cover, #fff 0%, #7db9e8 100%);
background: -o-radial-gradient(center, ellipse cover, #fff 0%, #7db9e8 100%);
background: -ms-radial-gradient(center, ellipse cover, #fff 0%, #7db9e8 100%);
background: radial-gradient(ellipse at center, #fff 0%, #7db9e8 100%);
color: #000;
}
.page--dark {
background: -moz-radial-gradient(center, ellipse cover, #444 0%, #111 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #444), color-stop(100%, #111));
background: -webkit-radial-gradient(center, ellipse cover, #444 0%, #111 100%);
background: -o-radial-gradient(center, ellipse cover, #444 0%, #111 100%);
background: -ms-radial-gradient(center, ellipse cover, #444 0%, #111 100%);
background: radial-gradient(ellipse at center, #444 0%, #111 100%);
color: #fff;
}
</style>
<div class="pages">
<div class="page page--dark"></div>
<div class="page page--light"></div>
<div class="page page--dark"></div>
<div class="page page--light"></div>
<div class="page page--dark"></div>
</div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>!function() {
var body = d3.select("body"),
height,
clientY0,
pageY0,
pageYMin = 0,
pageYMax,
dragSamples;
var page = d3.selectAll(".page")
.text(function(d, i) { return i; });
d3.select(window)
.on("resize", resized)
.on("touchstart", touchstarted)
.on("touchmove", touchmoved)
.on("touchend", touchended);
// iOS reports the wrong innerHeight on load!
d3.timer(function() {
resized();
return true;
});
function resized() {
var height0 = height;
height = innerHeight;
page.style("height", height + "px");
body.style("font", (height * .4) + "px/" + (height * .9) + "px sans-serif");
pageYMax = (page.size() - 1) * height;
if (height0) scrollTo(0, Math.max(0, Math.min(page.size() - 1, Math.round(pageYOffset / height0))) * height);
}
function touchstarted() {
dragSamples = [];
clientY0 = d3.event.changedTouches[0].clientY;
pageY0 = pageYOffset;
d3.event.preventDefault();
body.interrupt();
}
function touchmoved() {
var clientY1 = d3.event.changedTouches[0].clientY,
pageY1 = pageY0 + clientY0 - clientY1;
if (pageY1 < pageYMin) {
if (pageYOffset > pageYMin) scrollTo(0, pageYMin);
body.style("-webkit-transform", "translate3d(0," + -(pageY1 - pageYMin) / 3 + "px,0)");
} else if (pageY1 > pageYMax) {
if (pageYOffset < pageYMax) scrollTo(0, pageYMax);
body.style("-webkit-transform", "translate3d(0," + -(pageY1 - pageYMax) / 3 + "px,0)");
} else {
scrollTo(0, pageY1);
}
if (dragSamples.push({y: pageY1, t: Date.now()}) > 8) dragSamples.shift();
}
function touchended() {
var s0 = dragSamples.shift(),
s1 = dragSamples.pop(),
t1 = Date.now(),
y = pageYOffset;
while (s0 && (t1 - s0.t > 350)) s0 = dragSamples.shift();
if (s0 && s1) {
var vy = (s1.y - s0.y) / (s1.t - s0.t);
if (vy > .5) y = Math.ceil(y / height) * height;
else if (vy < -.5) y = Math.floor(y / height) * height;
}
y = Math.max(0, Math.min(page.size() - 1, Math.round(y / height))) * height;
body.transition()
.duration(500)
.ease("cubic-out")
.styleTween("-webkit-transform", function() {
if (s1) {
var i;
if (s1.y < pageYMin) i = d3.interpolateNumber(-(s1.y - pageYMin) / 3, 0);
if (s1.y > pageYMax) i = d3.interpolateNumber(-(s1.y - pageYMax) / 3, 0);
return i && function(t) { return "translate3d(0," + i(t) + "px,0)"; };
}
})
.tween("scroll", function() {
var i = d3.interpolateNumber(pageYOffset, y);
return function(t) { scrollTo(0, i(t)); };
});
}
}()</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment