Jim Vallandingham

@vlandham




2013

Abusing The Force

So You Think You Can Scroll

Jim Vallandingham

@vlandham




Scrolling

A Short History

"One of the most useful innovations in pointing devices"

Alan Cooper

Scrolling is a continuation

Clicking is a decision

Joshua Porter

Parallax Scrolling

Infinite Scrolling

Art Scrolling

Scrolling

In Visualization

Scrollable Dimension

One Mile Scroll

Active Satellites

1px Moon

Scrolling Triggers

Hottest Year

World Cup Balls

Scrolling Steps

Color Meanings

Clubs That Connect

Auto Sales

Battle At The Berrics

Scrolling Continuous

Russia Left Behind

Water

Lets Free Congress

Dawn Wall

Interactive Storytelling

Scrollytelling

Snow Fall

"The Web is a Storytelling Medium"

Bran Ferren

Daft Punk

Shark & Minnow

Scrollwork

Implementation Details

Demo

Potentially Humorous

Events

&

Transitions

Scroll Events

Detecting The Scroll

sectionPositions = [];
var startPos;
sections.each(function(d,i) {
  var top = this.getBoundingClientRect().top;
  if(i === 0) {
    startPos = top;
  }

  sectionPositions.push(top - startPos);
});
    
sectionPositions = [];
var startPos;
sections.each(function(d,i) {
  var top = this.getBoundingClientRect().top;
  if(i === 0) {
    startPos = top;
  }

  sectionPositions.push(top - startPos);
});
    
function position() {
  var pos = window.pageYOffset - 10;
  var sectionIndex = d3.bisect(sectionPositions, pos);
  sectionIndex = Math.min(sections.size() - 1, sectionIndex);

  if (currentIndex !== sectionIndex) {
    dispatch.active(sectionIndex);
    currentIndex = sectionIndex;
  }
}
function position() {
  var pos = window.pageYOffset - 10;
  var sectionIndex = d3.bisect(sectionPositions, pos);
  sectionIndex = Math.min(sections.size() - 1, sectionIndex);

  if (currentIndex !== sectionIndex) {
    dispatch.active(sectionIndex);
    currentIndex = sectionIndex;
  }
}
function position() {
  var pos = window.pageYOffset - 10;
  var sectionIndex = d3.bisect(sectionPositions, pos);
  sectionIndex = Math.min(sections.size() - 1, sectionIndex);

  if (currentIndex !== sectionIndex) {
    dispatch.active(sectionIndex);
    currentIndex = sectionIndex;
  }
}
// create dispatcher
var dispatch = d3.dispatch("active");
    
// create dispatcher
var dispatch = d3.dispatch("active");

// send event
dispatch.active(sectionIndex);
    
// create dispatcher
var dispatch = d3.dispatch("active");

// send event
dispatch.active(sectionIndex);

// listen for event
dispatch.on("active", function(index) {
  // ...
});
    
function position() {
  var pos = window.pageYOffset - 10;
  var sectionIndex = d3.bisect(sectionPositions, pos);
  sectionIndex = Math.min(sections.size() - 1, sectionIndex);

  if (currentIndex !== sectionIndex) {
    dispatch.active(sectionIndex);
    currentIndex = sectionIndex;
  }
}

Transitions

transition all the things

Transitions

Setup All Elements at the Start

function setupVis() {
  g.append("text")
    .attr("class", "sub-title openvis-title")
    .attr("x", width / 2)
    .attr("y", (height / 3) + (height / 5) )
    .text("OpenVis Conf");

  g.selectAll(".openvis-title")
    .attr("opacity", 0);

  // everything else ...
}
function setupVis() {
  g.append("text")
    .attr("class", "sub-title openvis-title")
    .attr("x", width / 2)
    .attr("y", (height / 3) + (height / 5) )
    .text("OpenVis Conf");

  g.selectAll(".openvis-title")
    .attr("opacity", 0);

  // everything else ...
}

Each Section Gets a Function


activateFunctions[0] = showTitle;
activateFunctions[1] = showFillerTitle;
activateFunctions[2] = showGrid;
activateFunctions[3] = highlightGrid;
activateFunctions[4] = showBar;
activateFunctions[5] = showHistPart;
activateFunctions[6] = showHistAll;
activateFunctions[7] = showCough;
activateFunctions[8] = showHistAll;
    
dispatch.on("active", function(index) {
  activateFunctions[index]();
}
    

Section Functions:

Show Themselves

Hide Their Neighbors

function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}
function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}
function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}
function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}

Everything is a Transition

Regular Transitions

Interrupted Transitions - Good!

Uninterrupted Transitions - Bad!

function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}
function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}
function showGrid() {
  g.selectAll(".count-title")
    .transition()
    .duration(0)
    .attr("opacity", 0);

  g.selectAll(".square")
    .transition()
    .duration(600)
    .delay(function(d,i) {
      return 5 * d.row;
    })
    .attr("opacity", 1.0)
    .attr("fill", "#ddd");
}

vallandingham.me/scroller.html

Dangers

In Scrolling

Scrolling is a continuation

Unless it is disrupted

How To Scroll

Mike Bostock

How To Scroll

Scrolljacking

Scrolling Mental Model

Inconsistent Metaphor?

Jesper Kiledal - Is Up Really Up?

Moving Window Model

Jesper Kiledal - Is Up Really Up?

Moving Document Model

Alternatives

"I miss the days of the stepper."

Anonymous Important Data Visualizer

College Gap

How Americans Die

3d of Economic Future

Mobilescroll?

Wrong to Scroll?

Or Just Too Slow?

Fewer Helmets More Deaths

Russia's Endgame

Swipe

The New Scroll?

Scrolltools

Libraries

graph-scroll

ScrollMagic

Skrollr

Swiper

Pleens

Odyssey.js

PageFlow

Special Thanks To:

Adam Pearce

@adamrpearce

Irene Ros

@ireneros

Lynn Cherny

@arnicas

Thanks

vallandingham.me

@vlandham

Thanks

vallandingham.me

@vlandham