I sommer begynte jeg å bygge en moderne fortelling av "Alice in Wonderland", en interaktiv storybook webapp med navnet Alice in Videoland. Det endte med å bli omtalt i en søsterartikkel i Adobe Inspire, og ble til en encore-vinnende presentasjon jeg ga på CSS Dev Conf 2013. Prosjektet var ment å være pedagogisk, en testmulighet for nye CSS animasjonsteknikker og desktop-to -tablet JavaScript. Jeg holder Alice kilden oppe på GitHub hvor noen kan undersøke koden min, men noen ganger er det fint å få noen til å gå over resonnementet med deg.
I denne artikkelen skal jeg dekke noen av de mest tekniske detaljene som hverken min snakke eller Inspire-artikkelen kan undersøke i dybden:
Hvis du vil lære om storyboarding, retina bilder, CSS animasjoner og andre interaksjoner, bør du sjekke ut den komplette artikkelen om Adobe Inspire. Også, før du leser videre, bør du definitivt spille med storybooken selv!
Målet mitt var enkelt nok: Lag en storybook-app som fungerte like godt i Chrome og på iOS Safari, spesielt på iPad-nettverket. Jeg tenkte på at jeg ikke hadde til hensikt å lage en "mobil kontekst", jeg visste nøyaktig hvor målgruppen ville være: på wifi-tilkoblinger, i hjemmets hjem, enten å lese med barna sine på runder eller dissekere koden ved kontoret.
Det tillot meg å bekymre seg mindre om nettleserkompatibilitet, en luksus få i produksjonsmiljøer har råd til. Men det er viktig at vi har slike prosjekter som hopper foran kurven fordi de hjelper oss å tenke på hva som vil være mulig i morgen.
Jeg hadde alltid likt "Alice in Wonderland" og "Through the Looking Glass" vokser opp, og jeg dove i å forske på og utvikle den nye verden og tegn som jeg ville skape med iver. Klare forskjeller i kunststiler måtte etableres, fra den impresjonistiske og sterile parken til den virkelige verden til midten av århundrets opprør av kaninens hull.
Hver karakter måtte ha sin egen historie og personlighet. På grunn av stramme tidsfrister, kunne jeg bare bringe en liten del av boken til livs. Jeg begynte med å skrive om åpningsscenen (som du kan lese ved å slå av CSS eller skrive ut storybookens side) og deretter lage et storyboard å gå med det.
Lær mer om kreativ prosess, tegn og miljødesign som gikk inn i "Alice in Videoland" i søsterseksjonen jeg skrev for Adobe Inspire.Fra blinkende øye til Alice gir jakten, blir animasjoner brukt subtilt gjennom hele historien for å gi en illusjon av livet, ikke ulikt en popup-bok. Men mens CSS-animasjoner støttes i alle moderne nettlesere, støtter ikke Internet Explorer 8 og under dem.
Hvis du har sjekket nettstedets trafikkrapporter, og et betydelig antall brukere er avhengige av Internet Explorer 8 eller tidligere (du sjekker alltid analysene dine før du designer, ikke?), Kan du fremdeles støtte disse nettleserne samtidig som de gir full interaksjon til moderne nettlesere . Webutviklingssamfunnet har møtt dette problemet før og har utviklet nå vanlige teknologier som webfonter og AJAX. Løsningen er enkel: brukere på moderne nettlesere får full erfaring, mens de som har mindre dyktige nettlesere, fortsatt får en forståelig og nyttig opplevelse. Walt Disney kan ha kalt denne "plussing" brukeropplevelsen. Webutviklere kaller det "progressiv forbedring" eller "grasiøs nedbrytning", avhengig av om du bygger for eldre eller nyere nettlesere først.
Når det gjelder animasjon, liker jeg å ta det jeg kaller Pop-Up Book Approach. For å illustrere er følgende videoer et eksempel på et interaktivt gavekort animasjon fra Square.com utviklet av Madelin Woods. (Takk, Madelin, for å ta opp disse!)
Personer i Internet Explorer 8 og lavere vil fortsatt glede seg over illustrasjonen og vil ikke legge merke til at den skal animeres, mens folk i nyere nettlesere vil bli underholdt ved den plussede animasjonen.
I Alice i Videoland gjorde jeg det samme. I scenen hvor hipster hvit kanin løper over skjermen, gjorde jeg ham sentrert og stasjonær hvis han ikke kunne bli animert. Jeg gjorde dette med modernizr.js.
Modernizr.js er en liten JavaScript-hjelper du kan sette på et nettsted for å sjekke om en nettleser støtter visse funksjoner som CSS3 animasjoner og overganger. Hvis funksjonene støttes, legger modernizr klassene til .cssanimations
og .csstransitions
til den overordnede HTML-taggen.
Jeg setter kaninens standardstil for å sitte på ham på siden. Hvis overganger er aktivert, bruker jeg .cstransitions klassen til å plassere ham fra venstre side av skjermen:
.kanin venstre: -50%; // kanin er sentrert .cstransitions .rabbit left: -100%; // kanin er skjult av venstre side av skjermen
Det er ikke bra å begynne å spille animasjoner mens alle bildene fortsatt lastes ned. Vi må sette opp en lasteskjerm til alt er klart å gå. jQuery skjer for å ha en metode kalt .laste
som bare brenner på bare en slik anledning. Jeg ga html
merk en standard klasse av .lasting
og brukte følgende bit av jQuery til å endre denne klassen til .lastet
så snart siden er fullt lastet og gjengitt:
$ (vindu) .load (funksjon () // Det er hyggelig å angi en kort timeout, slik at lastingen // siden har tid til å fullføre animasjonen setTimeout (funksjon () // endre tilstand til lastet $ ("html") .addClass ("loaded"). removeClass ("loading");, 4000););
Se Pen Alice i Videoland Load Screen av Rachel Nabors (@rachelnabors) på CodePen
Det er ganske enkelt å omfanget av CSS for laste skjermen til.lasting
og .lastet
klasser. Sjekk ut linje 9 i CSS i kodepen eksempelet. De padding
på beholderen overganger til 0
, forårsaker at lastskjermbildet "ruller opp". Linjer 108 til 128 styrer animasjoner Det fører til at koppen og tallerkenen faller etter at du har lagt til .laste
klasse til deres beholder. Noen av disse animasjonene, som kaninen kjører, bør bare skje når den delen av historien leses av leseren. Det er vanskelig å vite nøyaktig hvor brukerens øyne vil være på et gitt tidspunkt, men vi kan utlede det ved hjelp av den nydelige jQuery Waypoints plugin. Vi kan bruke den til å tildele en .in-visning-klasse til hver side. Når den rulles inn i en slik måte:
$ ("scene-park .page"). veipunkt (funksjon () // når denne .siden kommer i fokus, gi den en klasse "in-view" $ (dette) .addClass ("in-view" ););
Deretter sprer vi animasjonsstilene til .in-view-klassen, slik at de bare brenner etter rullet inn i visning.
Opprinnelig skulle jeg animere bakgrunnen bak Alice, men da prosjektet utviklet seg, innså jeg at effekten jeg egentlig ønsket, var at hun skulle falle mot bunnen av skjermen mens leserne rullet ned. Leserne måtte engasjere seg i historien for å se hva som skjer neste, og de ville bli belønnet ikke bare med en fremgang mot et mål (bunnen av siden), men også med endringer i Alice's humør fra skremt, til nysgjerrig, søvnig.
Først måtte jeg gjøre Alice klebrig. Det var at jeg måtte bytte henne til en fast stilling etter at leseren begynte å rulle, så hun ville ikke bla av toppen av siden. Jeg gjorde dette ved hjelp av den praktiske jQuery Waypoints snarveien for klissete elementer i stedet for å prøve å skrive mitt eget system.
For parallax-delen ble jeg avgjort på Skrollr, som virker ved å ta to numeriske dataattributter på et element, data-bildeelement-avstand
og interpolerer mellom dem, bildeelement-avstand
å være avstanden fra toppen av siden der endringene må begynne å skje. Siden tunneler er svært langt ned på siden, brukte jeg JavaScript til å måle avstanden fra toppen av siden, og jeg brukte høyden deres for å få disse datatributtene:
var tunnelTop = Math.round ($ tunnel.offset (). topp); var tunnelTopData = "data-" + tunnelTop; var tunnelBottomData = "data-" + (tunnelTop + Math.round ($ tunnel.height ())); // Gi Falling Alice hennes skrollr målinger som dataattributter $ alice.attr (tunnelTopData, "top: 0%"). Attr (tunnelBottomData, "topp: 80%");
Som gir meg noe som:
Se pennen som faller ned i kaninhullet av Rachel Nabors (@rachelnabors) på CodePen
I Safari på iOS, når du starter en rulle, berører du skjermen, skyver fingeren opp eller ned, og løfter fingeren fra skjermen. For å spare strøm, gjør ikke Safari noe mens fingeren berører skjermen. Det stopper alle animasjoner og kjører ikke engang JavaScript før du har fjernet fingeren.
I stedet tar det et øyeblikksbilde av skjermen og beveger det i retning av fingeren, og gir den illusjonen at du ruller som du gjør på skrivebordet. Men hvis siden inneholder animasjoner, er illusjonen brutt med hver rulle av fingeren. Dette betyr at en person kan rulle hele veien til bunnen av hullet, uten å engang stoppe for å legge merke til at Alice's humør endrer seg eller at hun faller:
Skrollr kommer med en mobil-vennlig funksjon som standard, som forsøker å løse dette problemet ved å bruke en CSS-transformasjon til hele siden og deretter animere den til en ny posisjon med CSS på bla. Denne metoden omgir imidlertid de rulleventyrene som Waypoints krever for å endre Alice's holdninger:
Dette er hvor jeg mistet damp. Jeg vurderte å sette opp det, så den fallende sekvensen var en animasjon på iPad og en rullende interaksjon på skrivebordet, men jeg hengte ideen. Først må jeg opprettholde to separate samspill og for det andre, hvis jeg var så aktiv i animasjonen, hvorfor gjorde jeg ikke bare en video av det?
Poenget med rullingsinteraksjonen er at det trekker leserne inn i historien; de styrer Alice. De er Alice. Det engasjerer dem. Hvis alt de trenger å gjøre er å klikke på kaninhullet, hva er poenget med det?
Jeg kontaktet mange repo-eiere og konsulterte Stack Overflow på jakt etter en løsning. Det var John Polacek, en av underleverandørene til et annet bibliotek Super Scrollorama, som foreslo at jeg tok en titt på Hammer.js, et lite JavaScript-bibliotek for håndtering av bevegelser som klemme og swiping på mobile enheter (som har en versjon som plugger direkte inn i jQuery !) Jeg hadde sett på biblioteket tidlig i utviklingen og valgt å forfølge det, men jeg bestemte meg for å se igjen.
Jeg brukte mye tid på å se hvordan folk beveget seg gjennom historien ved å trykke på iPad. Jeg la merke til at de ikke rullet ned på siden så mye som å sveipe. Jeg trodde at hvis jeg kunne kartlegge fremgangen av historien fra en side til en swiping-handling, kunne jeg fortsatt opprettholde et ganske nært forhold mellom både desktop og touch-opplevelser. Hammer.js tillot meg å koble til swipe hendelser på iPad, og jeg var i stand til å gjøre det slik at ved å sveipe, lesere avanserte til neste side:
hvis (Modernizr.touch) // Sveip til forrige side $ (dokument) .hammer (prevent_default: true). på ("swipedown", funksjon (hendelse) scrollPageIntoCenter ($ (". prevPage)); currentPage = prevPage; calcPrevNext (currentPage););
Dette er en enorm forenkling av koden. For dette berøringsbaserte brukstilfellet måtte jeg ty til å holde styr på dagens, forrige og neste side ved hjelp av tellervariabler. Det er også noen interessante ting som skjer med omberegning av høyder og lignende på skiftende miljøer. Jeg anbefaler at du tar en titt på kildekoden (hjelpsomt annotert!) Hvis du virkelig vil få hendene skitne.
Et av problemene med å utvikle for iPads er at klikkene ikke kartlegges direkte til kraner. Når du klikker på en kobling i iOS Safari, er det en liten pause mens systemet dobbelt sjekker at du ikke skal gjøre noen form for gest. Det spør, "Er du sikker på at du vil følge den linken? Eller klemmer du eller dobbeltklikker? "Dette gjør at klikkbaserte samhandlinger virker svake og unaturlige.
I vårt tilfelle, når kaninhullet klikkes eller tappes, vil vi at det skal utføres downTheHole ()
funksjon som ruller siden ned i jorden. Løsningen er å bruke begge klikk
og touchend
hendelse lyttere! Rodney Rehm hjalp meg med å lage en mer effektiv versjon av originalen min (slås på)
metode. Etter det er det lett å ringe slik:
$ ( "# To-tunneler") aktivere (downTheHole.);
Alice in Videoland vil alltid være et arbeid pågår for meg. Etter hvert som tiden tillater, kan jeg gå tilbake for å utvide antallet enheter og nettlesere hun utfører sømløst. Eller jeg kan gå videre og legge til nye kapitler i historien for å demonstrere ting som lerret, SVG-animasjoner eller API for webanimasjon.
Jeg er alltid åpen for nye måter å skrive kode på og gjøre gammel kode kjører raskere. Jeg håper at "Alice" vil tjene som en lang og storiedemo av ting rett rundt hjørnet for interaksjonsdesign.