Alice in Videoland

Building an interactive storybook in HTML5

with Rachel Nabors
RachelNabors.com
@RachelNabors

Rachel the Great and her talking cat Tuna, waving.
You can still read the comic adventures of Rachel and Tuna at RacheltheGreat.com
Tin Magpie
Now I tell stories using my front-end development skills at my company, TinMagpie.com

The Project

The Quest

Write an article for Adobe's Inspire zine that will:

And get paid to tell a story. (Much harder than it seems.)

What we'll cover

Updating Alice

This isn't Alice. Illustration by John Tenniel

Disney's Alice Illustration by Mary Blair

Burton's Alice

American McGee's Alice

Quin Rose's Alice

The world doesn't need another blonde and/or blue Alice.

For reals.

The Real Alice (Liddell) c. 1862

Our Alice, just a curious little girl

Alice's Sister, Denise

The whitest rabbit you know

The Park

The Hole

Formulating the Experience

Rewriting the Original

Alice was beginning to get very bored, sitting by her sister in the park. Her sister was deeply engrossed in a technical book about web development.

“How can she read a book with no pictures or dialog in it?” Alice wondered to herself.

She was just about to nod off when suddenly a white rabbit wearing a vintage tweed porkpie hat dashed by… looking anxiously at his smartphone!

And so on. To see the full copy, try printing the page.

Time for a real storyboard.

Constraints

The final Alice in Videoland “storybook”.

Solving for Retina

I took the
“Big Graphics,
Big Compression” approach.

Because I know my use case.

SVG

Comparing SVG rendering in FireFox to Chrome: FireFox is noticeably blurred.
FireFox scales small SVGs up poorly.

JPG

Setting Compression to 0 in Photoshop's Save to Web Dialog

PNG

Streamlining and Automation

Loading

Loading hidden scenes

The load screen disappears after $(window).load().

All the scenes must remain hidden while the page's images load and DOM renders.

load() will fire without display: none's background images.

But opacity: 0 elements background images must be downloaded to fire load().

.loading .scene {
  opacity: 0;
}

Animating the Load Screen

Follow along at cdpn.io/modpi

Tracking Reading Progress

Using jQuery Waypoints

My Twitter friend Kevin Lozandier reminded me about jQuery Waypoints

$(element).waypoint(function() {
  doSomething();
}, { offset: someNumber });  // of pixels from the top

Only works with visible things.

Calculating which page is being read

We can assume that if a page is of equal distance from top as from bottom, it's being read.

var beingRead = function() {
  var $screenHeight = $.waypoints('viewportHeight');
  var $pageHeight = $(".page").height();
  var offset = ($pageHeight - $screenHeight) / 2 * -1;

  return offset;
}

Using Waypoints when you reveal things

// fired when rabbit hole is clicked
var downTheHole = function() {
  $tunnel.find(".page").waypoint(function() {
    $(this).addClass("in-view");
    // more stuff...
  }, {
    offset: beingRead()
  });
};

Additional Uses for Waypoints

Dealing with Resizes

There's a lot of math being done, and all of it relies on measuring visible elements. You'll have to re/take these measurements whenever:

Recalculating Waypoints

Assume someone turns their iPad. All that math for nothing!

Not so!

var recalcWaypoints = function() {
  $(".page").waypoint({
    offset: beingRead()
  });
}

window.addEventListener('orientationchange', recalcWaypoints);

Parallaxin' Down the Rabbit Hole

Using Skrollr

I used skrollr.js.

Follow along at cdpn.io/AeEHw

Calculating the Fall

I put the following into downTheHole():

// calculate the height of the tunnels
var tunnelTop = Math.round($tunnel.offset().top);
var tunnelTopData = "data-" + tunnelTop;
var tunnelBottomData =  "data-" + (tunnelTop + Math.round($tunnel.height()));

$alice.waypoint('sticky') // make her sticky!
.attr(tunnelTopData, "top:0%").attr(tunnelBottomData, "top:80%");   // Give Falling Alice her skrollr measurements as data attributes

Changing Alice's Mood

Remember calculating those waypoints?

$tunnel.find(".page").waypoint(function() {
  $(this).addClass("in-view");
  var mood = $(this).data("mood");
  $("body").removeClass().addClass(mood);
}, {
  offset: beingRead()
});

Tie those classes to different background-positions on Alice's sprite.

From “Click and Scroll”
to “Tap and Swipe”

It's not “mobile.”
It's “touch.”

Mapping Tap to Click

My original function was good.

Rodney Rehm offered up a better solution.

// To get to #tunnels, activate #tunnels
$("#to-tunnels").activate(downTheHole);

The Perils of Parallax

Danger! In iOS Safari, all animation and JavaScript pauses while you touch the screen.

Skrollr has a “solution” for that.

This leads to an intesting puzzle:

So either you can change Alice's mood and everything jumps or her mood doesn't change but she parallaxes fine.

Gestures with Hammer.js

An email conversation with John Polacek convinced me to take another look at hammer.js.

Originally I attached it to all .pages, but…

Tracking Progress on Touch

In the land of scrolling, Waypoints is enough.

In the land of touch, it was important to:

So I used counters.

Wrapping it in modernizr

I was already using Modernizr to test for CSS animations/transitions support.

var cutToWonderland = function() {
  if(Modernizr.touch) {
    cutFired = true;
    currentPage = nextPage;
    calcPrevNext(currentPage);
  }
  // ...
}

People tell stories. Plural.

In web development, every story has many authors.

To be continued…

Text #storytelling 5 Brilliant! to 504-229-6828

Do eet.

Thank you!

CSS 4EVAH!

Now tell the story!!

/

#