Add old platform coop free software presentation

This commit is contained in:
Benjamin Melançon 2018-05-29 18:28:30 -04:00
parent cba39ae3e6
commit e4b79b6bf7
18 changed files with 10229 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,008 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

View file

@ -0,0 +1,26 @@
Copyright (c) 2012, Michael Bostock
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name Michael Bostock may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,10 @@
# Platform Cooperatives and Free Software
Slides for a presentation. <!-- View <a href="http://mlncn.github.io//">index.html</a> in a browser, but view the source for my notes. -->
# Built on stack.js
Stack.js is a presentation library with intuitive, scroll-based navigation.
https://mbostock.github.io/stack/
https://github.com/mbostock/stack

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

9294
platform-coop-free-software/d3.v3.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,387 @@
<!DOCTYPE html>
<html>
<head>
<title>Platform Cooperatives and Free Software</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
@import url(http://fonts.googleapis.com/css?family=Ubuntu:500|Quattrocento+Sans:400,700,400italic);
section {
background-color: white;
color: black;
padding: 2em;
font-family: "Quattrocento Sans", Helvetica, Verdana, sans-serif;
font-weight: 400;
background-size: cover;
}
section.reverse {
background-color: #0678be;
color: white;
}
a:link,
a:visited {
color: #99CCFF;
text-decoration: none;
}
section.reverse a:link,
section.reverse a:visited {
color: yellow;
}
a:hover {
text-decoration: underline;
}
section p {
font-size: 1em;
line-height: 1.4;
}
section strong {
font-weight: 700;
}
h1,h2,h3,h4,h5,h6 {
font-family: Ubuntu, Arial, sans-serif;
font-weight: 500;
text-align: center;
}
h1 {
font-size: 2em;
}
.big li {
font-size: 1.2em;
}
img {
margin-left: auto;
margin-right: auto;
}
cite {
font-size: .8em;
color: #eee;
position: absolute;
bottom: 0;
}
.dark {
color: #111;
}
.dark a {
color: #0678be;
}
blockquote cite {
color: inherit;
display: block;
position: relative;
text-align: right;
padding-right: 1em;
}
blockquote cite::before {
content: "—";
}
.notes {
display: none !important;
}
@media print {
.notes {
display: block;
}
}
</style>
</head>
<body>
<section class="reverse" style="padding-top: 2em">
<h1>Platform Cooperatives<br />and Free Software</h1>
<h2></h2>
<h4><a href="https://pad.riseup.org/p/platform-coop-free-software">pad.riseup.org/p/platform-coop-free-software</a></h4>
<h4><a href="https://mlncn.withknown.com/">@mlncn</a><br />
<a href="http://agaric.com/">agaric.com</a></h4>
</section>
<div class="notes">
Hello! All blame in this presentation can go to that guy's twitter handle right there.
</div>
<section style="background-image:url(2273635564_efcaf3250a_o.jpg);">
<cite><a href="https://www.flickr.com/photos/neubie/2273635564">Neubie</a>, Money Hand</cite>
</section>
<div class="notes">
Free software has a funding problem.
We were at a Drupal meetup last night. Almost the entire room used directly built on Free Software to earn their living. Ninety percent of the room used proprietary 'integrated development environments' . If free software can't win in this market, how is it going to win among the billions more people who need Free Software to have control over their loves, but don't even know about it yet?
</div>
<section style="background-image:url(jeep-in-ditch-recall-IMG_0724.jpg);">
<cite><a href="https://www.wired.com/2015/07/hackers-remotely-kill-jeep-highway/">Andy Greenberg: Hackers Remotely Kill a Jeep on the Highway—With Me in It</a></cite>
</section>
<div class="notes">
Here's a hacked jeep driven into a ditch.
"Computers and the Internet are everywhere and the world is increasingly made of them."
Cory Doctorow
</div>
<section style="background-image:url(plane-crash-do-to-software-bug.jpg);">
<cite><a href="http://www.bbc.com/news/technology-32810273">BBC: Airbus A400M plane crash linked to software fault</a></cite>
</section>
<div class="notes">
It is hard to convince people — in other audiences — that it matters what code runs on their devices, in their bodies, and for services they use from the cloud. Richard Stallman has been working on this for decades. I have this 50 minute presentation and more things to cover, so here's a scary picture.
<p>This is an Airbus A400M crashed due to a software fault, four crew members killed. As a web developer, i have always been very grateful that my mistakes would be hard-pressed to kill anyone. I think the political and economic consequences of not having control of our software is the big danger, but it really is a matter of life and death. Which is not to say that software of all kinds has not made us safer, and won't make great leaps in safety in the future.</p>
So free software matters. Why isn't it winning?
</div>
<section style="background-image: url(Walled_Garden_-_geograph.org.uk_-_229821.jpg);">
<blockquote><big>walled gardens are winning<br />
because they have a superior<br />
<strong>user experience</strong></big>
<cite>Dries Buytaert</cite>
</blockquote>
<cite>Dries Buytaert, <a href="http://buytaert.net/winning-back-the-open-web">Winning back the open web</a></cite>
</section>
<div class="notes">
The superior user experience is paid for by piles more cash than the average free software project gets, and disciplined by paying customers— whether they are paying with money, or with their time, attention, and personal data.
<p>So free software needs a business model. Where could it find one, just one step away?</p>
</div>
<section class="reverse">
<h2>Almost all SaaS services are already built on Free Software.</h2>
</section>
<div class="notes">
<p>Free Software has the best maintainability and scalability. Every hot startup or excellent service you can think of, from Facebook to Slack to AirBnB to Google, uses Free Software. The entire stack of almost all of them are built on Free Software, from GNU/Linux to Apache to Nginx to PHP to Python to React.js... it's just the last thing they put together with all this Free Software that's not being shared, because the founders or the owners are looking to multiply their investments by hundreds of times, which they can only do by holding a monopoly by any means available, including proprietary software. So we can't re-use the funding model which proprietary software as a service is using, but while we're looking for a business model, software as a service, interpreted broadly, seems to be where it's at.</p>
<p>Okay, then, let's look at *Free* Software as a Service. Where does it have a competitive advantage?</p>
</div>
<section class="reverse">
<h3>Free Software as a Service</h3>
<h2>Freedom to take data <em>and</em> functionality elsewhere</h2>
</section>
<div class="notes">
Only Free Software guarantees complete ability to pack up and leave after a crisis—political, economic, technical—with the service provider.
</div>
<section class="reverse">
<h3>Free Software as a Service</h3>
<h2>Freedom to take the platform in a new direction</h2>
</section>
<div class="notes">
Likewise for picking up and going in a new direction.
<p>These might map pretty close to a certain four freedoms...</p>
</div>
<section class="reverse">
<h3>Free Software as a Service</h3>
<h2>Security for development partners</h2>
</section>
<div class="notes">
Only Free Software ensures people building their service businesses providing costomizations and design on a platform have an opportunity to take their customizations to another level for select customers who grow into greanter needs.
<p>And, like the customers on the platform whom they serve, they can take their clients elsewhere if the platform no longer aligns with their interests.</p>
<p>The business-savvy will be noticing that these advantages are attractive to customers and development partners, but still rather altruistic from the perspective of the business itself.</p>
</div>
<section class="reverse">
<h3>Platform Cooperatives</h3>
<h2>Customers first</h2>
</section>
<div class="notes">
Only a cooperative puts customers, the people who need the service, in control of if and how any surplus is used.
<p>SaaS, like licensed software, too often is used by a company to keep extracting revenue without putting value back in. Atrophying of software platforms is highly innefficient fo the economy at large— for example, competitors have to start from scratch and redo everything, including acquiring customers. Importantly, it is also inefficient for customers specifically, because they often have to incur switching costs to get to a platform that has invested in significant improvements recently.</p>
</div>
<section class="reverse">
<h3>Platform Cooperatives</h3>
<h2>Ownership effect</h2>
</section>
<div class="notes">
<p>The primary beneficiaries, stakeholders of the platform, are, as owners, more emotinoally invested in the platform and are more engaged in participatory planning, beta testing, user research, boosting monetary contributions when called for— which can be especially valuable before launch.</p>
</div>
<section style="background-image: url(Torn_down_blockbuster_2013.jpeg);">
<blockquote><big>As value shifts from software to the ability to leverage data, companies will have to rethink their businesses, just as Netflix and Google did.</big>
<cite>Dries Buytaert</cite>
</blockquote>
<cite>Dries Buytaert, <a href="http://buytaert.net/the-future-of-software-is-data-driven">The future of software is data-driven</a></cite>
</section>
<div class="notes">
This shift has the potential to greatly advantage cooperatives, and, if you'll pardon the phrase, liberate software used by platforms to be free software— like all the components in the stack making this software already, it won't be the competitive edge for most companies. Instead, the competitive edge may be the trustworthiness of networks and the stewardship of data— and the one-member, one-vote ownership of platform cooperatives may engender greater trust.
</div>
<section>
</section>
<div class="notes">
</div>
<section style="background-image:url(internet-of-ownership-first-screen.png);">
<h3 style="margin-top: -1em"><a href="http://internetofownership.net/">InternetOfOwnership.net</a></h3>
</section>
<div class="notes">
Platform cooperatives, a twist on the century-old ideas of consumer, producer, and solidarity cooperatives, are already becoming a movement. They featured at the national conference of worker cooperatives that ended last week.
You can learn about many of the players at InternetOfOwnership.net.
[Talk about some favorites.]
</div>
<section style="background-image: url(climate-disaster-photo-by-theritters.jpg);">
</section>
<div class="notes">
Can platform cooperativism and free software really save humanity? When global warming is an overarching threat to ... everything? They can help.
Staying with the example of oil, gas, and coal companies... why do corporations do such evil things as destroy the planet for the profit of a few? The key is in that word 'few'— the benefits are sharply concentrated, and this is made even worse by the stripping of responsibility from the benefit, and the costs are distributed among all.
</div>
<section style="background-image: url(Cities_City_landscape_on_the_shore_of_the_sea_043951_.jpg);">
</section>
<div class="notes">
By distributing both benefit and responsibility for oversight more broadly, platform cooperatives help decisions get made with broader societal benefit in mind. Free software helps make power more distributed generally.
</div>
<section class="reverse" style="padding:6em 10em; background-image: url(turtle-in-sand.png); background-size: contain; background-position: bottom center; background-repeat: no-repeat;">
<h4><a href="https://pad.riseup.org/p/platform-coop-free-software">pad.riseup.org/p/platform-coop-free-software</a></h4>
<h4><a href="http://mlncn.withknown.com/" rel="author">benjamin melançon</a></h4>
<h5><a href="mailto:ben@agaric.com">ben@agaric.com</a></h5>
<h5><a href="https://twitter.com/mlncn">@mlncn</a></h5>
</section>
<section id="lorenz" style="text-align:center;padding-top:0;">
<canvas></canvas>
</section>
<section style="background-image: url(climate-disaster-photo-by-theritters.jpg);">
<h2 style="margin-top: 10em">.</h2>
<cite><a href="https://www.flickr.com/photos/littlesister/">IndyDina</a>, ""</cite>
</section>
<section class="reverse" style="background-image:url(doctorow-civilwar-spreadsheet.jpeg);">
<blockquote style="background-color: black; padding: 0.5em"><big><big> </big></big></blockquote>
<cite>Cory Doctorow, <a href="http://boingboing.net/2012/08/23/civilwar.html">"The coming civil war over general purpose computing"</a></cite>
</section>
<section style="background-image:url(1413479953ewaste2.jpg);">
</section>
<section>
<h2></h2>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</section>
<script src="d3.v3.min.js"></script>
<script src="stack.v1.js"></script>
<script>
var mystack = stack()
.on("activate", activate)
.on("deactivate", deactivate);
var section = d3.selectAll("section"),
lorenz = d3.select("#lorenz"),
lorenzIndex = section[0].indexOf(lorenz.node());
function activate(d, i) {
if (i === lorenzIndex) startLorenz();
}
function deactivate(d, i) {
if (i === lorenzIndex) stopLorenz();
}
var lorenzInterval;
function startLorenz() {
var δτ = 0.003,
ρ = 28,
σ = 10,
β = 8 / 3,
x = .5,
y = .5,
z = 10,
n = 30;
var width = 1280,
height = 720;
var canvas = d3.select("canvas")
.style("position", "absolute")
.style("top", 0)
.style("left", 0)
.style("width", "100%")
.style("height", "100%")
.attr("width", width)
.attr("height", height);
var color = d3.scale.linear()
.domain([0, 20, 30, 50])
.range(["yellow", "orange", "brown", "purple"])
.interpolate(d3.interpolateHcl);
var context = canvas.node().getContext("2d");
context.lineWidth = .2;
context.fillStyle = "rgba(0,0,0,.03)";
d3.timer(function() {
context.save();
context.globalCompositeOperation = "lighter";
context.translate(width / 2, height / 2);
context.scale(12, 14);
context.rotate(30);
for (var i = 0; i < n; ++i) {
context.strokeStyle = color(z);
context.beginPath();
context.moveTo(x, y);
x += δτ * σ * (y - x);
y += δτ * (x * (ρ - z) - y);
z += δτ * (x * y - β * z);
context.lineTo(x, y);
context.stroke();
}
context.restore();
return !lorenzInterval;
});
lorenzInterval = setInterval(function() {
context.fillRect(0, 0, width, height);
}, 100);
}
function stopLorenz() {
lorenzInterval = clearInterval(lorenzInterval);
}
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View file

@ -0,0 +1,55 @@
body {
background: #929292;
font-family: "Helvetica Neue";
margin: auto;
width: 1280px;
}
a {
color: #6baed6;
}
a:not(:hover) {
text-decoration: none;
}
.stack {
background: #222 url(cartographer.png);
color: #fff;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
display: none;
font-size: 48px;
height: 800px;
padding: 160px 80px;
width: 1280px;
-webkit-transform: translate3d(0,0,0);
}
.active {
box-shadow: 0px 4px 8px rgba(0,0,0,.5);
display: block;
position: fixed;
}
.grey {
color: #969696;
}
@media
screen and (max-device-width: 1024px) {
body {
width: 1200px;
}
.stack {
margin: 40px 0;
}
.stack {
display: block;
}
}

View 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;
})();

View file

@ -0,0 +1 @@
var stack=function(){function t(t){return K-1>d&&d==f&&d>t?(d-=.5-m/u/2,scrollTo(0,d*u),e(),!0):void 0}function e(){var t=Math.floor(d)+(d%1?.5:0);if(t!==T){var e={};if(e[Math.floor(t)]=1,e[Math.ceil(t)]=1,T>=0){var n={};n[Math.floor(T)]=1,n[Math.ceil(T)]=1;for(var a in n)a in e?delete e[a]:y.deactivate.call(k[0][+a],+a)}for(var a in e)y.activate.call(k[0][+a],+a);T=t}}function n(){m=(window.innerHeight-u)/2,v=1+m/u,d3.select(g).style("margin-top",m+"px").style("margin-bottom",m+"px").style("height",(K-.5)*u+m+"px")}function a(){var t=+location.hash.slice(1);isNaN(t)||t===f||p.position(t)}function l(){var t;switch(d3.event.keyCode){case 39:if(d3.event.metaKey)return;case 40:case 34:t=d3.event.metaKey?1/0:1;break;case 37:if(d3.event.metaKey)return;case 38:case 33:t=d3.event.metaKey?-1/0:-1;break;case 32:t=d3.event.shiftKey?-1:1;break;default:return}c&&(c=clearTimeout(c)),null==h&&(h=(t>0?Math.floor:Math.ceil)(d==f?f:d+(.5-m/u/2))),p.position(h=Math.max(0,Math.min(K-1,h+t))),d3.event.preventDefault()}function o(){g!==x&&x.scrollTop&&(g=x);var n=Math.max(0,g.scrollTop/u);if(n>=K-1.51+m/u&&(n=K-1),!t(n)){var a=Math.max(0,Math.floor(d=n)),l=Math.min(v,2*(d%1));f!=a&&(location.replace("#"+a),f=a),k.classed("active",!1),d3.select(k[0][f]).style("-webkit-transform",l?"translate3d(0,"+-l*u+"px,0)":null).style("-o-transform",l?"translate(0,"+-l*u+"px)":null).style("-moz-transform",l?"translate(0,"+-l*u+"px)":null).style("transform",l?"translate(0,"+-l*u+"px)":null).classed("active",l!=v),d3.select(k[0][f+1]).style("-webkit-transform",l?"translate3d(0,0,0)":null).style("-o-transform",l?"translate(0,0)":null).style("-moz-transform",l?"translate(0,0)":null).style("transform",l?"translate(0,0)":null).classed("active",l>0),e()}}function r(){var t=d3.event.clientY;if(t!==i&&(i=t,null==h)){var e=p.position(),n=Math.max(0,Math.round(e+.25));0>=e||e>=K-1.51+m/u||(n>e&&.5-m/u>n-e?scrollTo(0,n*u):n!==e&&p.position(n))}}function s(t){return function(){var e=d3.interpolateNumber(this.scrollTop,t*u);return function(t){scrollTo(0,e(t)),o()}}}var c,i,u,d,f,h,v,m,p={},y=d3.dispatch("activate","deactivate"),k=d3.selectAll("section"),M=d3.select(window),g=document.body,x=document.documentElement,b=250,w="cubic-in-out",T=-1,K=k[0].length;return k.classed("stack",!0).style("z-index",function(t,e){return K-e}),k.classed("active",!0),u=k.node().getBoundingClientRect().height,k.classed("active",!1),p.position=function(e){var n=g.scrollTop/u;return arguments.length<1?n:(e>=K?e=K-1:0>e&&(e=Math.max(0,K+e)),e=Math.floor(e),n-e&&(M.on("scroll.stack",null),t(e),d3.select(g).transition().duration(b).ease(w).tween("scrollTop",s(h=e)).each("end",function(){h=null,M.on("scroll.stack",o)})),location.replace("#"+e),p)},k.style("display")!="block"?(M.on("keydown.stack",l).on("resize.stack",n).on("scroll.stack",o).on("mousemove.stack",r).on("hashchange.stack",a),n(),a(),o(),p.duration=function(t){return arguments.length?(b=t,p):b},p.ease=function(t){return arguments.length?(w=t,p):w},d3.rebind(p,y,"on"),p):void 0}();

View file

@ -0,0 +1,231 @@
function stack() {
var stack = {},
size = [1280, 720],
fontSize = 32,
sectionHeight,
windowHeight,
dispatch = d3.dispatch("scroll", "activate", "deactivate"),
touchy = "ontouchstart" in document,
resize = touchy ? resizeTouchy : resizeNoTouchy,
i = NaN,
y = 0,
yt,
scrollRatio = 1 / 6;
var section = d3.selectAll("section")
.style("box-sizing", "border-box")
.each(initialize);
var n = section.size();
var body = d3.select("body")
.style("margin", 0)
.style("padding", 0)
.style("background", "#333");
if (touchy) {
section
.style("position", "relative");
d3.select(window)
.on("resize.stack", resize)
.each(resize);
} else {
var background = d3.select("body").insert("div", "section")
.style("background", "#000")
.style("box-shadow", "0 8px 16px rgba(0,0,0,.3)")
.style("padding", "1px 0")
.style("margin-top", "-1px")
.style("z-index", 0);
section
.style("display", "none")
.style("opacity", 0)
.style("z-index", 0);
var sectionAndBackground = d3.selectAll(section[0].concat(background.node()))
.style("position", "fixed")
.style("left", 0)
.style("top", 0)
.style("width", "100%");
var indicator = d3.select("body").append("div")
.attr("class", "indicator")
.selectAll("div")
.data(d3.range(section.size()))
.enter().append("div")
.style("position", "absolute")
.style("z-index", 10)
.style("left", 0)
.style("width", "3px")
.style("background", "linear-gradient(to top,black,white)");
var sectionPrevious = d3.select(null),
sectionCurrent = d3.select(section[0][0]),
sectionNext = d3.select(section[0][1]);
d3.select(window)
.on("resize.stack", resize)
.on("scroll.stack", reposition)
.on("keydown.stack", keydown)
.each(resize);
d3.timer(function() {
reposition();
return true;
});
}
function dispatchEvent(event, i) {
var target = section[0][i], sourceEvent = event.sourceEvent = d3.event;
try {
d3.event = event;
dispatch[event.type].call(target, target.__data__, i);
} finally {
d3.event = sourceEvent;
}
}
function initialize(d, i) {
this.__stack__ = {index: i, active: false};
}
function activate() {
if (!this.__stack__.active) {
this.__stack__.active = true;
dispatchEvent({type: "activate"}, this.__stack__.index);
}
}
function deactivate() {
if (this.__stack__.active) {
this.__stack__.active = false;
dispatchEvent({type: "deactivate"}, this.__stack__.index);
}
}
function resizeTouchy() {
var marginBottom = 20;
sectionHeight = size[1] / size[0] * innerWidth;
windowHeight = innerHeight;
section
.style("height", sectionHeight + "px")
.style("box-shadow", "0 4px 4px rgba(0,0,0,.3)")
.filter(function(d, i) { return i < n - 1; })
.style("margin-bottom", marginBottom + "px");
body
.style("font-size", innerWidth / size[0] * fontSize + "px");
}
function resizeNoTouchy() {
if (sectionHeight) var y0 = y;
sectionHeight = size[1] / size[0] * innerWidth;
windowHeight = innerHeight;
sectionAndBackground
.style("top", (windowHeight - sectionHeight) / 2 + "px")
.style("height", sectionHeight + "px");
indicator
.style("top", function(i) { return (i + (1 - scrollRatio) / 2) * windowHeight + "px"; })
.style("height", windowHeight * scrollRatio + "px");
body
.style("font-size", innerWidth / size[0] * fontSize + "px")
.style("height", windowHeight * n + "px");
// Preserve the current scroll position on resize.
if (!isNaN(y0)) scrollTo(0, (y = y0) * windowHeight);
}
function reposition() {
var y1 = pageYOffset / windowHeight,
i1 = Math.max(0, Math.min(n - 1, Math.floor(y1 + (1 + scrollRatio) / 2)));
if (i !== i1) {
if (i1 === i + 1) { // advance one
sectionPrevious.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
sectionPrevious = sectionCurrent.interrupt().style("opacity", 1).style("z-index", 1);
sectionPrevious.transition().each("end", deactivate);
sectionCurrent = sectionNext.interrupt().style("opacity", 0).style("z-index", 2).each(activate);
sectionCurrent.transition().style("opacity", 1);
sectionNext = d3.select(section[0][i1 + 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0);
} else if (i1 === i - 1) { // rewind one
sectionNext.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
sectionNext = sectionCurrent.interrupt().style("opacity", 1).style("z-index", 1);
sectionNext.transition().each("end", deactivate);
sectionCurrent = sectionPrevious.interrupt().style("opacity", 0).style("z-index", 2).each(activate);
sectionCurrent.transition().style("opacity", 1);
sectionPrevious = d3.select(section[0][i1 - 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0);
} else { // skip
sectionPrevious.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
sectionCurrent.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
sectionNext.interrupt().style("display", "none").style("opacity", 0).style("z-index", 0).each(deactivate);
sectionPrevious = d3.select(section[0][i1 - 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0).each(deactivate);
sectionCurrent = d3.select(section[0][i1]).interrupt().style("display", "block").style("opacity", 1).style("z-index", 2).each(activate);
sectionNext = d3.select(section[0][i1 + 1]).interrupt().style("display", "block").style("opacity", 0).style("z-index", 0).each(deactivate);
}
i = i1;
}
dispatchEvent({type: "scroll", offset: y = y1}, i);
}
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;
}
var y0 = isNaN(yt) ? y : yt;
yt = Math.max(0, Math.min(n - 1, (delta > 0
? Math.floor(y0 + (1 + scrollRatio) / 2)
: Math.ceil(y0 - (1 - scrollRatio) / 2)) + delta));
d3.select(document.documentElement)
.interrupt()
.transition()
.duration(500)
.tween("scroll", function() {
var i = d3.interpolateNumber(pageYOffset, yt * windowHeight);
return function(t) { scrollTo(0, i(t)); };
})
.each("end", function() { yt = NaN; });
d3.event.preventDefault();
}
stack.size = function(_) {
return arguments.length ? (size = [+_[0], +_[1]], resize(), stack) : size;
};
stack.scrollRatio = function(_) {
return arguments.length ? (scrollRatio = +_, resize(), stack) : scrollRatio;
};
stack.fontSize = function(_) {
return arguments.length ? (fontSize = +_, resize(), stack) : fontSize;
};
d3.rebind(stack, dispatch, "on");
return stack;
}

View file

@ -0,0 +1 @@
function stack(){function e(e,t){var n=b[0][t],i=e.sourceEvent=d3.event;try{d3.event=e,h[e.type].call(n,n.__data__,t)}finally{d3.event=i}}function t(e,t){this.__stack__={index:t,active:!1}}function n(){this.__stack__.active||(this.__stack__.active=!0,e({type:"activate"},this.__stack__.index))}function i(){this.__stack__.active&&(this.__stack__.active=!1,e({type:"deactivate"},this.__stack__.index))}function s(){var e=20;o=p[1]/p[0]*innerWidth,r=innerHeight,b.style("height",o+"px").style("box-shadow","0 4px 4px rgba(0,0,0,.3)").filter(function(e,t){return k-1>t}).style("margin-bottom",e+"px"),z.style("font-size",innerWidth/p[0]*u+"px")}function l(){if(o)var e=_;o=p[1]/p[0]*innerWidth,r=innerHeight,w.style("top",(r-o)/2+"px").style("height",o+"px"),M.style("top",function(e){return(e+(1-g)/2)*r+"px"}).style("height",r*g+"px"),z.style("font-size",innerWidth/p[0]*u+"px").style("height",r*k+"px"),isNaN(e)||scrollTo(0,(_=e)*r)}function a(){var t=pageYOffset/r,s=Math.max(0,Math.min(k-1,Math.floor(t+(1+g)/2)));v!==s&&(s===v+1?(K.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),K=N.interrupt().style("opacity",1).style("z-index",1),K.transition().each("end",i),N=W.interrupt().style("opacity",0).style("z-index",2).each(n),N.transition().style("opacity",1),W=d3.select(b[0][s+1]).interrupt().style("display","block").style("opacity",0).style("z-index",0)):s===v-1?(W.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),W=N.interrupt().style("opacity",1).style("z-index",1),W.transition().each("end",i),N=K.interrupt().style("opacity",0).style("z-index",2).each(n),N.transition().style("opacity",1),K=d3.select(b[0][s-1]).interrupt().style("display","block").style("opacity",0).style("z-index",0)):(K.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),N.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),W.interrupt().style("display","none").style("opacity",0).style("z-index",0).each(i),K=d3.select(b[0][s-1]).interrupt().style("display","block").style("opacity",0).style("z-index",0).each(i),N=d3.select(b[0][s]).interrupt().style("display","block").style("opacity",1).style("z-index",2).each(n),W=d3.select(b[0][s+1]).interrupt().style("display","block").style("opacity",0).style("z-index",0).each(i)),v=s),e({type:"scroll",offset:_=t},v)}function c(){var e;switch(d3.event.keyCode){case 39:if(d3.event.metaKey)return;case 40:case 34:e=d3.event.metaKey?1/0:1;break;case 37:if(d3.event.metaKey)return;case 38:case 33:e=d3.event.metaKey?-1/0:-1;break;case 32:e=d3.event.shiftKey?-1:1;break;default:return}var t=isNaN(y)?_:y;y=Math.max(0,Math.min(k-1,(e>0?Math.floor(t+(1+g)/2):Math.ceil(t-(1-g)/2))+e)),d3.select(document.documentElement).interrupt().transition().duration(500).tween("scroll",function(){var e=d3.interpolateNumber(pageYOffset,y*r);return function(t){scrollTo(0,e(t))}}).each("end",function(){y=0/0}),d3.event.preventDefault()}var o,r,y,d={},p=[1280,720],u=32,h=d3.dispatch("scroll","activate","deactivate"),x="ontouchstart"in document,f=x?s:l,v=0/0,_=0,g=1/6,b=d3.selectAll("section").style("box-sizing","border-box").style("line-height","1.35em").each(t),k=b.size(),z=d3.select("body").style("margin",0).style("padding",0).style("background","#333");if(x)b.style("position","relative"),d3.select(window).on("resize.stack",f).each(f);else{var m=d3.select("body").insert("div","section").style("background","#000").style("box-shadow","0 8px 16px rgba(0,0,0,.3)").style("padding","1px 0").style("margin-top","-1px").style("z-index",0);b.style("display","none").style("opacity",0).style("z-index",0);var w=d3.selectAll(b[0].concat(m.node())).style("position","fixed").style("left",0).style("top",0).style("width","100%"),M=d3.select("body").append("div").attr("class","indicator").selectAll("div").data(d3.range(b.size())).enter().append("div").style("position","absolute").style("z-index",10).style("left",0).style("width","3px").style("background","linear-gradient(to top,black,white)"),K=d3.select(null),N=d3.select(b[0][0]),W=d3.select(b[0][1]);d3.select(window).on("resize.stack",f).on("scroll.stack",a).on("keydown.stack",c).each(f),d3.timer(function(){return a(),!0})}return d.size=function(e){return arguments.length?(p=[+e[0],+e[1]],f(),d):p},d.scrollRatio=function(e){return arguments.length?(g=+e,f(),d):g},d.fontSize=function(e){return arguments.length?(u=+e,f(),d):u},d3.rebind(d,h,"on"),d}