Rename future is here presentation folder
This commit is contained in:
parent
54d52373f8
commit
3699383696
32 changed files with 0 additions and 0 deletions
219
future-here/stack.v0.js
Normal file
219
future-here/stack.v0.js
Normal file
|
@ -0,0 +1,219 @@
|
|||
var stack = (function() {
|
||||
var stack = {},
|
||||
event = d3.dispatch("activate", "deactivate"),
|
||||
section = d3.selectAll("section"),
|
||||
self = d3.select(window),
|
||||
body = document.body,
|
||||
root = document.documentElement,
|
||||
timeout,
|
||||
duration = 250,
|
||||
ease = "cubic-in-out",
|
||||
screenY,
|
||||
size,
|
||||
yActual,
|
||||
yFloor,
|
||||
yTarget,
|
||||
yActive = -1,
|
||||
yMax,
|
||||
yOffset,
|
||||
n = section[0].length;
|
||||
|
||||
// Invert the z-index so the earliest slides are on top.
|
||||
section.classed("stack", true).style("z-index", function(d, i) { return n - i; });
|
||||
|
||||
// Detect the slide height (by showing an active slide).
|
||||
section.classed("active", true);
|
||||
size = section.node().getBoundingClientRect().height;
|
||||
section.classed("active", false);
|
||||
|
||||
// Sets the stack position.
|
||||
stack.position = function(y1) {
|
||||
var y0 = body.scrollTop / size;
|
||||
if (arguments.length < 1) return y0;
|
||||
|
||||
// clamp and round
|
||||
if (y1 >= n) y1 = n - 1;
|
||||
else if (y1 < 0) y1 = Math.max(0, n + y1);
|
||||
y1 = Math.floor(y1);
|
||||
|
||||
if (y0 - y1) {
|
||||
self.on("scroll.stack", null);
|
||||
leap(y1);
|
||||
d3.select(body).transition()
|
||||
.duration(duration)
|
||||
.ease(ease)
|
||||
.tween("scrollTop", tween(yTarget = y1))
|
||||
.each("end", function() { yTarget = null; self.on("scroll.stack", scroll); });
|
||||
}
|
||||
|
||||
location.replace("#" + y1);
|
||||
|
||||
return stack;
|
||||
};
|
||||
|
||||
// Don't do anything fancy for iOS.
|
||||
if (section.style("display") == "block") return;
|
||||
|
||||
self
|
||||
.on("keydown.stack", keydown)
|
||||
.on("resize.stack", resize)
|
||||
.on("scroll.stack", scroll)
|
||||
.on("mousemove.stack", snap)
|
||||
.on("hashchange.stack", hashchange);
|
||||
|
||||
resize();
|
||||
hashchange();
|
||||
scroll();
|
||||
|
||||
// if scrolling up, jump to edge of previous slide
|
||||
function leap(yNew) {
|
||||
if ((yActual < n - 1) && (yActual == yFloor) && (yNew < yActual)) {
|
||||
yActual -= .5 - yOffset / size / 2;
|
||||
scrollTo(0, yActual * size);
|
||||
reactivate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function reactivate() {
|
||||
var yNewActive = Math.floor(yActual) + (yActual % 1 ? .5 : 0);
|
||||
if (yNewActive !== yActive) {
|
||||
var yNewActives = {};
|
||||
yNewActives[Math.floor(yNewActive)] = 1;
|
||||
yNewActives[Math.ceil(yNewActive)] = 1;
|
||||
if (yActive >= 0) {
|
||||
var yOldActives = {};
|
||||
yOldActives[Math.floor(yActive)] = 1;
|
||||
yOldActives[Math.ceil(yActive)] = 1;
|
||||
for (var i in yOldActives) {
|
||||
if (i in yNewActives) delete yNewActives[i];
|
||||
else event.deactivate.call(section[0][+i], +i);
|
||||
}
|
||||
}
|
||||
for (var i in yNewActives) {
|
||||
event.activate.call(section[0][+i], +i);
|
||||
}
|
||||
yActive = yNewActive;
|
||||
}
|
||||
}
|
||||
|
||||
function resize() {
|
||||
yOffset = (window.innerHeight - size) / 2;
|
||||
yMax = 1 + yOffset / size;
|
||||
|
||||
d3.select(body)
|
||||
.style("margin-top", yOffset + "px")
|
||||
.style("margin-bottom", yOffset + "px")
|
||||
.style("height", (n - .5) * size + yOffset + "px");
|
||||
}
|
||||
|
||||
function hashchange() {
|
||||
var hash = +location.hash.slice(1);
|
||||
if (!isNaN(hash) && hash !== yFloor) stack.position(hash);
|
||||
}
|
||||
|
||||
function keydown() {
|
||||
var delta;
|
||||
switch (d3.event.keyCode) {
|
||||
case 39: // right arrow
|
||||
if (d3.event.metaKey) return;
|
||||
case 40: // down arrow
|
||||
case 34: // page down
|
||||
delta = d3.event.metaKey ? Infinity : 1; break;
|
||||
case 37: // left arrow
|
||||
if (d3.event.metaKey) return;
|
||||
case 38: // up arrow
|
||||
case 33: // page up
|
||||
delta = d3.event.metaKey ? -Infinity : -1; break;
|
||||
case 32: // space
|
||||
delta = d3.event.shiftKey ? -1 : 1;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
if (timeout) timeout = clearTimeout(timeout);
|
||||
if (yTarget == null) yTarget = (delta > 0 ? Math.floor : Math.ceil)(yActual == yFloor ? yFloor : yActual + (.5 - yOffset / size / 2));
|
||||
stack.position(yTarget = Math.max(0, Math.min(n - 1, yTarget + delta)));
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
|
||||
function scroll() {
|
||||
// Detect whether to scroll with documentElement or body.
|
||||
if (body !== root && root.scrollTop) body = root;
|
||||
|
||||
var yNew = Math.max(0, body.scrollTop / size);
|
||||
if (yNew >= n - 1.51 + yOffset / size) yNew = n - 1;
|
||||
|
||||
// if scrolling up, jump to edge of previous slide
|
||||
if (leap(yNew)) return;
|
||||
|
||||
var yNewFloor = Math.max(0, Math.floor(yActual = yNew)),
|
||||
yError = Math.min(yMax, (yActual % 1) * 2);
|
||||
|
||||
if (yFloor != yNewFloor) {
|
||||
location.replace("#" + yNewFloor);
|
||||
yFloor = yNewFloor;
|
||||
}
|
||||
|
||||
section
|
||||
.classed("active", false);
|
||||
|
||||
d3.select(section[0][yFloor])
|
||||
.style("-webkit-transform", yError ? "translate3d(0," + (-yError * size) + "px,0)" : null)
|
||||
.style("-o-transform", yError ? "translate(0," + (-yError * size) + "px)" : null)
|
||||
.style("-moz-transform", yError ? "translate(0," + (-yError * size) + "px)" : null)
|
||||
.style("transform", yError ? "translate(0," + (-yError * size) + "px)" : null)
|
||||
.classed("active", yError != yMax);
|
||||
|
||||
d3.select(section[0][yFloor + 1])
|
||||
.style("-webkit-transform", yError ? "translate3d(0,0,0)" : null)
|
||||
.style("-o-transform", yError ? "translate(0,0)" : null)
|
||||
.style("-moz-transform", yError ? "translate(0,0)" : null)
|
||||
.style("transform", yError ? "translate(0,0)" : null)
|
||||
.classed("active", yError > 0);
|
||||
|
||||
reactivate();
|
||||
}
|
||||
|
||||
function snap() {
|
||||
var y = d3.event.clientY;
|
||||
if (y === screenY) return; // ignore move on scroll
|
||||
screenY = y;
|
||||
|
||||
if (yTarget != null) return; // don't snap if already snapping
|
||||
|
||||
var y0 = stack.position(),
|
||||
y1 = Math.max(0, Math.round(y0 + .25));
|
||||
|
||||
// if we're before the first slide, or after the last slide, do nothing
|
||||
if (y0 <= 0 || y0 >= n - 1.51 + yOffset / size) return;
|
||||
|
||||
// if the previous slide is not visible, immediate jump
|
||||
if (y1 > y0 && y1 - y0 < .5 - yOffset / size) scrollTo(0, y1 * size);
|
||||
|
||||
// else transition
|
||||
else if (y1 !== y0) stack.position(y1);
|
||||
}
|
||||
|
||||
function tween(y) {
|
||||
return function() {
|
||||
var i = d3.interpolateNumber(this.scrollTop, y * size);
|
||||
return function(t) { scrollTo(0, i(t)); scroll(); };
|
||||
};
|
||||
}
|
||||
|
||||
stack.duration = function(_) {
|
||||
if (!arguments.length) return duration;
|
||||
duration = _;
|
||||
return stack;
|
||||
};
|
||||
|
||||
stack.ease = function(_) {
|
||||
if (!arguments.length) return ease;
|
||||
ease = _;
|
||||
return stack;
|
||||
};
|
||||
|
||||
d3.rebind(stack, event, "on");
|
||||
|
||||
return stack;
|
||||
})();
|
Loading…
Add table
Add a link
Reference in a new issue