Cómo lo hicieron: Alicia en Videolandia
() translation by (you can also view the original English article)
Este verano empecé a construir un moderno recuento de "Alicia en el País de las Maravillas", una aplicación web interactiva de libros de cuentos llamada Alicia en Videolandia. Terminó apareciendo en un artículo hermano en Adobe Inspire, además de convertirse en una presentación ganadora de encore que di en CSS Dev Conf 2013. El proyecto pretendía ser educativo, un campo de pruebas para nuevas técnicas de animación CSS y JavaScript de escritorio a tableta. Mantengo el código fuente de Alicia en GitHub donde cualquiera puede examinar mi código, pero a veces es bueno tener a alguien que repase el razonamiento contigo.
En este artículo cubriré algunos de los detalles más técnicos que ni mi charla ni el artículo de Inspire pudieron examinar en profundidad:
- Usando Modernizr.js con animaciones para mejorar la degradación con gracia
- Detectar qué página se está leyendo con jQuery Waypoints
- Añadiendo paralaje de desplazamiento con Skrollr.js
- Superar los problemas de desplazamiento y deslizamiento en el iPad
- Toque de mapeo para hacer clic
Si quieres aprender sobre el storyboarding, las imágenes de la retina, las animaciones CSS y otras interacciones, debes ver el artículo suplementario sobre Adobe Inspire. Además, antes de seguir leyendo, ¡debes jugar con el libro de historias en sí!
Un libro de cuentos para el iPad y Chrome
Mi objetivo era bastante simple: hacer una aplicación de libro de cuentos que funcionara igual de bien en Chrome y en iOS Safari, específicamente en el iPad Retina. No estaba diseñando para un "contexto móvil", sabía exactamente dónde estaría mi público objetivo: en conexiones wifi, en la comodidad de sus casas, leyendo con sus hijos en sus regazos o diseccionando el código en la oficina.
Eso me permitió preocuparme menos por la compatibilidad del navegador, un lujo que pocos en entornos de producción pueden permitirse. Pero es importante que tengamos proyectos como este que se adelanten a la curva porque nos ayudan a pensar en lo que será posible mañana.



Siempre me gustó "Alicia en el País de las Maravillas" y "A través del espejo" mientras crecía, y me sumergí en la investigación y el desarrollo del nuevo mundo y los personajes que crearía con celo. Había que establecer claras diferencias en los estilos de arte, desde el parque impresionista y estéril del mundo real hasta el motín de mediados de siglo de la madriguera del conejo.
Cada personaje tenía que tener su propia historia y personalidad. Debido a los apretados plazos, solo pude dar vida a una pequeña parte del libro. Empecé reescribiendo la escena inicial (que puedes leer apagando el CSS o imprimiendo la página del libro de cuentos) y luego creando un storyboard para acompañarla.
Degradación elegante y aumento progresivo
Desde el parpadeo del ojo hasta la persecución de Alicia, las animaciones se utilizan sutilmente a lo largo de la historia para dar la ilusión de vida, no muy diferente de un libro popup. Sin embargo, mientras que las animaciones CSS son soportadas en todos los navegadores modernos, Internet Explorer 8 y posteriores no las soportan.
Si has comprobado los informes de tráfico de tu sitio y un número significativo de tus usuarios confías en Internet Explorer 8 o anterior (siempre compruebas tus análisis antes de diseñar, ¿verdad?), puedes seguir siendo compatible con esos navegadores a la vez que ofreces la interacción completa a los navegadores modernos. La comunidad de desarrollo de la web se ha enfrentado a este problema anteriormente y ha desarrollado tecnologías ahora comunes como las fuentes web y AJAX. La solución es simple: los usuarios de los navegadores modernos obtienen una experiencia completa, mientras que los de los navegadores menos capaces siguen obteniendo una experiencia inteligible y útil. Walt Disney podría haber llamado a esto "plussing" la experiencia del usuario. Los desarrolladores web lo llaman "mejora progresiva" o "degradación elegante", dependiendo de si se construye primero para navegadores más antiguos o más nuevos.
Cuando se trata de animación, me gusta tomar lo que yo llamo el enfoque de los libros pop-up. Para ilustrarlo, los siguientes videos son un ejemplo de una animación interactiva de tarjeta de regalo de Square.com diseñada por Madelin Woods. (¡Gracias, Madelin, por grabar esto!)
Los usuarios de Internet Explorer 8 y versiones inferiores seguirán encantados con la ilustración y no notarán que debe ser animada, mientras que los usuarios de los navegadores más recientes se divertirán con la animada.
En Alicia en Videolandia, hice lo mismo. En la escena en la que el conejo blanco hipster corre por la pantalla, lo hice centrado y estacionario si no podía ser animado. Lo hice con modernizr.js.
Modernizr.js
Modernizr.js es un pequeño ayudante de JavaScript que se puede poner en un sitio para comprobar si un navegador soporta ciertas características como animaciones y transiciones CSS3. Si las características son soportadas, modernizr añade las clases .cssanimations
y .csstransitions
a la etiqueta HTML principal.
Establecí los estilos por defecto del conejo para centrarlo en la página. Si las transiciones están habilitadas, uso la clase .csstransitions para reposicionarlo fuera del lado izquierdo de la pantalla:
1 |
.rabbit { |
2 |
left: -50%; // rabbit is centered |
3 |
}
|
4 |
|
5 |
.csstransitions .rabbit { |
6 |
left: -100%; // rabbit is hidden off left side of screen |
7 |
}
|



La pantalla de carga
No sirve de nada empezar a jugar a las animaciones mientras todas las imágenes se siguen descargando. Necesitamos poner una pantalla de carga hasta que todo esté listo. jQuery tiene un método llamado .load
que solo se dispara en una ocasión así. Le di a la etiqueta html
una clase por defecto de .loading
y usé el siguiente bit de jQuery para cambiar esa clase a .loaded
tan pronto como la página esté completamente cargada y renderizada:
1 |
$(window).load(function() { |
2 |
// It’s nice to set a short timeout so the loading |
3 |
// page has time to complete its animation |
4 |
|
5 |
setTimeout(function(){ |
6 |
// change state to loaded |
7 |
$("html").addClass("loaded").removeClass("loading"); |
8 |
}, 4000); |
9 |
}); |
Vea la pantalla de carga del bolígrafo Alicia en Videolandia de Rachel Nabors (@rachelnabors) en CodePen
.loading
y .loaded
. Mira la línea 9 del CSS en el ejemplo del codepen. El padding
en el contenedor de transiciiones pasa a 0
, causando que la pantalla de carga se "enrolle". Las líneas 108 a 128 controlan las animaciones que hacen que la taza y el platillo se caigan después de agregar la clase .load
a su contenedor. Saber qué página se está leyendo
Algunas de estas animaciones, como el conejo corriendo, solo deben ocurrir cuando esa parte de la historia está siendo leída por el lector. Es difícil saber exactamente dónde estarán los ojos de un usuario en un momento dado, pero podemos inferirlo usando el encantador plugin jQuery Waypoints. Podemos usarlo para asignar una clase .in-view a cada .página cuando se desplaza a la vista de esta manera:
1 |
$(".scene-park .page").waypoint(function() { |
2 |
// when this .page comes into focus, give it a class of “in-view” |
3 |
$(this).addClass("in-view"); |
4 |
}); |
Luego revisamos los estilos de animación en la clase .in-view para que solo se disparen después de haberlos visto,
Bajo la madriguera del conejo con paralaje
Originalmente iba a animar el fondo detrás de Alicia, pero a medida que el proyecto avanzaba, me di cuenta de que el efecto que realmente quería era que ella cayera hacia el fondo de la pantalla mientras los lectores se desplazaban hacia abajo. Los lectores tendrían que comprometerse con la historia para ver qué pasa después, y serían recompensados no solo con una progresión hacia una meta (la parte inferior de la página), sino también con cambios en el estado de ánimo de Alicia, que pasaría de estar asustada, a ser curiosa, a estar somnolienta.
Primero, tuve que hacer a Alicia pegajosa. Es decir, tenía que hacerla cambiar a una posición fija después de que el lector empezara a desplazarse, para que no se saliera de la parte superior de la página. Lo hice usando el práctico atajo de jQuery Waypoints para elementos pegajosos en lugar de intentar escribir mi propio sistema.
Para la parte de paralaje, me decidí por Skrollr, que funciona tomando dos atributos de datos numéricos de un elemento, data-pixel-distance
e interpolando entre ellos, siendo pixel-distance
la distancia desde la parte superior de la página en la que los cambios deben comenzar a ocurrir. Como los túneles están muy abajo en la página, usé Javascript para medir su distancia desde la parte superior de la página, y usé su altura para obtener esos atributos de datos:
1 |
var tunnelTop = Math.round($tunnel.offset().top); |
2 |
var tunnelTopData = "data-" + tunnelTop; |
3 |
var tunnelBottomData = "data-" + (tunnelTop + Math.round($tunnel.height())); |
4 |
|
5 |
// Give Falling Alice her skrollr measurements as data attributes |
6 |
|
7 |
$alice.attr(tunnelTopData, "top:0%").attr(tunnelBottomData, "top:80%"); |
Lo que me da algo como:
1 |
</pre>
|
2 |
<div data-5205="top:0%" data-9810="top:80%"></div> |
3 |
<pre>
|
Ver el bolígrafo cayendo en la madriguera del conejo por Rachel Nabors (@rachelnabors) en CodePen
Desplazamiento y deslizamiento en un iPad
En Safari en iOS, cuando inicias un desplazamiento, tocas la pantalla, deslizas tu dedo hacia arriba o hacia abajo y luego levantas el dedo de la pantalla. Para ahorrar energía, Safari no hace nada mientras tu dedo toca la pantalla. Detiene todas las animaciones y ni siquiera ejecuta JavaScript hasta que hayas quitado el dedo.
En cambio, toma una instantánea de la pantalla y la mueve en la dirección de tu dedo, dando la ilusión de que te estás desplazando como lo haces en el escritorio. Pero si la página contiene animaciones, la ilusión se rompe con cada rollo de tu dedo. Esto significa que una persona podría desplazarse hasta el fondo del agujero sin detenerse una sola vez para notar que el humor de Alicia está cambiando o que está cayendo:
Skrollr viene con una característica de fácil manejo para los móviles por defecto, que intenta solucionar este problema aplicando una transformación CSS a toda la página y luego animándola a una nueva posición con CSS en el desplazamiento. Sin embargo, este método evita los eventos de desplazamiento que requieren las balizas para cambiar las actitudes de Alicia:
Quedar atrapado en la madriguera del conejo
Aquí es donde perdí el control. Pensé en configurarlo para que la secuencia de caída fuera una animación en el iPad y una interacción de desplazamiento en el escritorio, pero detestaba la idea. Primero, tendría que mantener dos interacciones separadas y segundo, si estaba animando tanto el cuento, ¿por qué no hice un video de él?
El punto de la interacción de desplazamiento es que atrae a los lectores a la historia; ellos controlan a Alicia. Ellos son Alicia. Los atrae. Si todo lo que tienen que hacer es hacer clic en la madriguera del conejo, ¿cuál es el punto de eso?
Contacté a muchos propietarios de reposiciones y consulté a Stack Overflow en busca de una solución. Fue John Polacek, uno de los mantenedores de otra biblioteca Super Scrollorama, quien me sugirió que echara un vistazo a Hammer.js, una pequeña biblioteca de JavaScript para el manejo de gestos como pellizcar y deslizar en los dispositivos móviles (que tiene una versión que se conecta directamente a jQuery!) Había mirado la biblioteca al principio del desarrollo y opté por no seguir adelante, pero decidí mirar de nuevo.
Es la hora del martillo
Pasé mucho tiempo viendo cómo la gente se movía a través de la historia usando el toque en el iPad. Me di cuenta de que no se desplazaban tanto por la página como por el deslizamiento. Pensé que si podía hacer un mapa avanzando la historia por una página hasta una acción de golpeteo, podría mantener una relación bastante estrecha entre las experiencias de escritorio y las de tacto. Hammer.js me permitió engancharme a los eventos de swipe en el iPad, y fui capaz de hacer que en el swipe, los lectores avanzaran a la siguiente página:
1 |
if(Modernizr.touch) { |
2 |
//Swipe to previous page |
3 |
$(document).hammer({prevent_default:true}).on("swipedown", function(event) { |
4 |
scrollPageIntoCenter($(".page").get(prevPage)); |
5 |
currentPage = prevPage; |
6 |
calcPrevNext(currentPage); |
7 |
}); |
8 |
} |
Esta es una simplificación masiva del código. Para este caso de uso táctil, tuve que recurrir a llevar un registro de las páginas actuales, anteriores y siguientes usando variables de contador. También hay algunas cosas interesantes que suceden con el recalculo de las alturas y tales en los ambientes cambiantes. Te recomiendo encarecidamente que le eches un vistazo al código fuente (¡apuntado de forma útil!) si realmente quieres ensuciarte las manos.
Golpeteo vs. Cliqueo
Uno de los problemas de desarrollar para iPads es que los clics no se dirigen directamente a los golpes. Cuando pulsas un enlace en el iOS Safari, se produce una ligera pausa mientras el sistema comprueba que no vas a hacer ningún tipo de gesto. Está preguntando, "¿Estás seguro de que quieres seguir ese enlace? ¿O estás pellizcando o dando doble golpe?" Esto hace que las interacciones basadas en el clic se sientan lentas y poco naturales.
En nuestro caso, cuando la madriguera del conejo es pulsada o golpeada, queremos que ejecute la función downTheHole()
que desplaza la página hacia abajo en la tierra. La solución es utilizar tanto a ¡los oyentes de eventos de click
y touchend
! Rodney Rehm me ayudó a hacer una versión más eficiente de mi método original activate()
. Después de lo cual, es fácil llamar así:
1 |
$("#to-tunnels").activate(downTheHole); |
Un trabajo en progreso
Alicia en Videolandia siempre será un trabajo en progreso para mí. A medida que el tiempo lo permita, puedo volver a ampliar el número de dispositivos y navegadores en los que se desenvuelve sin problemas. O puedo avanzar y añadir nuevos capítulos a la historia para demostrar cosas como el lienzo, las animaciones SVG o la API de animación web.
Siempre estoy abierto a nuevas formas de escribir código y hacer que el viejo código funcione más rápido. Espero que "Alicia" sirva como una larga e histórica demostración de las cosas que están a la vuelta de la esquina para el diseño de interacción.