Crea con Chrome

Portare i mattoncini LEGO® sul web multi-dispositivo

Hans Eklund
Hans Eklund

Build with Chrome, un divertente esperimento per gli utenti di Chrome per computer lanciato originariamente in Australia, è stato ripubblicato nel 2014 con disponibilità a livello globale, promozioni legate a THE LEGO® MOVIE™ e il supporto appena aggiunto per i dispositivi mobili. In questo articolo condivideremo alcuni insegnamenti del progetto, in particolare in merito al passaggio dall'esperienza solo desktop a una soluzione multischermo che supporta sia il mouse sia il tocco.

La storia di Build with Chrome

La prima versione di Crea con Chrome è stata lanciata in Australia nel 2012. Volevamo dimostrare la potenza del web in un modo completamente nuovo e portare Chrome a un pubblico completamente nuovo.

Il sito era composto da due parti principali: la modalità "Costruisci", in cui gli utenti potevano creare costruzioni utilizzando i mattoncini LEGO, e la modalità "Esplora", per sfogliare le creazioni su una versione LEGO di Google Maps.

Il 3D interattivo era essenziale per offrire agli utenti la migliore esperienza di costruzione LEGO. Nel 2012, WebGL era disponibile pubblicamente solo nei browser desktop, quindi Build era destinata a essere un'esperienza solo per computer. Esplora utilizzava Google Maps per visualizzare le creazioni, ma quando si avvicinava abbastanza, passava a un'implementazione WebGL della mappa che mostrava le creazioni in 3D, utilizzando comunque Google Maps come texture della base. Volevamo creare un ambiente in cui gli appassionati di LEGO di tutte le età potessero esprimere facilmente e intuitivamente la propria creatività ed esplorare le creazioni degli altri.

Nel 2013 abbiamo deciso di estendere Build with Chrome a nuove tecnologie web. Tra queste tecnologie c'era WebGL in Chrome per Android, che naturalmente avrebbe consentito a Build with Chrome di evolversi in un'esperienza mobile. Per iniziare, abbiamo sviluppato prima dei prototipi touch prima di interrogare l'hardware per lo "strumento per la creazione" per comprendere il comportamento dei gesti e la reattività tattile che potremmo riscontrare tramite un browser rispetto a un'app mobile.

Un front-end adattabile

Dovevamo supportare i dispositivi con input tocco e mouse. Tuttavia, l'utilizzo della stessa UI su piccoli touchscreen si è rivelato una soluzione non ottimale a causa di limitazioni di spazio.

In Build è presente un'interattività molto elevata: puoi aumentare e diminuire lo zoom, cambiare i colori dei mattoni e, naturalmente, selezionarli, ruotarli e posizionarli. È uno strumento in cui gli utenti trascorrono spesso molto tempo, quindi è importante che abbiano accesso rapido a tutto ciò che usano di frequente e che si sentano a proprio agio a interagire con esso.

Quando progetti un'applicazione tocco altamente interattiva, scoprirai che lo schermo sembra subito piccolo e che le dita dell'utente tendono a coprire gran parte dello schermo durante l'interazione. Questo è diventato evidente per noi quando abbiamo lavorato con il builder. Quando crei il design, devi considerare le dimensioni fisiche dello schermo anziché i pixel della grafica. Diventa importante ridurre al minimo il numero di pulsanti e controlli per avere il maggior spazio possibile sullo schermo dedicato ai contenuti effettivi.

Il nostro obiettivo era rendere Build naturale sui dispositivi touch, non solo aggiungendo l'input tocco all'implementazione desktop originale, ma facendo in modo che sembrasse davvero progettato per il tocco. Abbiamo ottenuto due varianti dell'interfaccia utente, una per computer e tablet con schermi di grandi dimensioni e una per dispositivi mobili con schermi più piccoli. Se possibile, è meglio utilizzare una singola implementazione e avere una transizione fluida tra le modalità. Nel nostro caso, abbiamo stabilito che esisteva una differenza così significativa nell'esperienza tra queste due modalità che abbiamo deciso di fare affidamento su un punto di interruzione specifico. Le due versioni hanno molte funzionalità in comune e abbiamo cercato di fare la maggior parte delle cose con un'unica implementazione di codice, ma alcuni aspetti dell'interfaccia utente funzionano in modo diverso tra le due.

Utilizziamo i dati dell'user-agent per rilevare i dispositivi mobili e poi controlliamo le dimensioni del viewport per decidere se utilizzare l'interfaccia utente mobile per schermi piccoli. È un po' difficile scegliere un punto di interruzione per definire che cosa sia uno "schermo grande", perché è difficile ottenere un valore affidabile delle dimensioni fisiche dello schermo. Fortunatamente, nel nostro caso non importa molto se mostriamo l'interfaccia utente per schermi piccoli su un dispositivo touch con uno schermo grande, perché lo strumento funzionerà comunque correttamente, solo che alcuni pulsanti potrebbero sembrare un po' troppo grandi. Alla fine, abbiamo impostato il punto di interruzione su 1000 pixel; se carichi il sito da una finestra più larga di 1000 pixel (in modalità Orizzontale), visualizzerai la versione per schermi di grandi dimensioni.

Parliamo un po' delle due dimensioni dello schermo e delle due esperienze:

Schermo grande, con supporto per mouse e tocco

La versione per schermi grandi viene pubblicata su tutti i computer con supporto del mouse e sui dispositivi touch con schermi grandi (come Google Nexus 10). Questa versione è simile alla soluzione desktop originale per quanto riguarda i tipi di controlli di navigazione disponibili, ma abbiamo aggiunto il supporto del tocco e alcuni gesti. Modifichiamo l'interfaccia utente in base alle dimensioni della finestra, quindi quando un utente ne modifica le dimensioni, parte dell'interfaccia utente potrebbe essere rimossa o ridimensionata. A tale scopo utilizziamo le query supporti CSS.

Esempio: quando l'altezza disponibile è inferiore a 730 pixel, il controllo del cursore dello zoom in modalità Esplora è nascosto:

@media only screen and (max-height: 730px) {
    .zoom-slider {
        display: none;
    }
}

Schermo piccolo, solo supporto tocco

Questa versione viene pubblicata su dispositivi mobili e tablet di piccole dimensioni (dispositivi target Nexus 4 e Nexus 7). Questa versione richiede il supporto multi-touch.

Sui dispositivi con schermi di piccole dimensioni, dobbiamo dare ai contenuti il maggior spazio possibile, quindi abbiamo apportato alcune modifiche per massimizzare lo spazio, soprattutto nascondendo gli elementi usati di rado:

  • Il selettore dei blocchi di costruzione si riduce a un selettore di colori durante la creazione.
  • Abbiamo sostituito i controlli di zoom e orientamento con gesti multi-touch.
  • La funzionalità a schermo intero di Chrome è utile anche per avere più spazio sullo schermo.
Creare contenuti su uno schermo di grandi dimensioni
Crea annunci su uno schermo di grandi dimensioni. Il selettore di blocchi è sempre visibile e sul lato destro sono presenti un paio di controlli.
Creare annunci su uno schermo piccolo
Sviluppa su uno schermo di piccole dimensioni. Il selettore di blocchi è ridotto a icona e alcuni pulsanti sono stati rimossi.

Rendimento e supporto di WebGL

I dispositivi touch moderni dispongono di GPU abbastanza potenti, ma sono ancora lontani dalle loro controparti desktop, quindi sapevamo che avremmo avuto alcuni problemi di prestazioni, in particolare nella modalità Esplora 3D, in cui dobbiamo eseguire il rendering di molte creazioni contemporaneamente.

Dal punto di vista creativo, volevamo aggiungere un paio di nuovi tipi di mattoni con forme complesse e persino trasparenti, funzionalità che in genere richiedono molta potenza della GPU. Tuttavia, dovevamo garantire la compatibilità con le versioni precedenti e continuare a supportare le creazioni della prima versione, quindi non potevamo impostare nuove limitazioni, ad esempio ridurre notevolmente il numero totale di blocchi nelle creazioni.

Nella prima versione di Build era presente un limite massimo di blocchi che potevano essere utilizzati in una creazione. C'era un "misuratore di mattoni" che indicava quanti mattoni erano rimasti. Nella nuova implementazione, alcuni dei nuovi mattoni influiscono sul contatore dei mattoni più di quelli standard, riducendo leggermente il numero massimo totale di mattoni. Questo era un modo per includere nuovi elementi mantenendo un rendimento decente.

Nella modalità Esplora 3D vengono eseguite diverse operazioni contemporaneamente: caricamento delle texture della piastra di base, caricamento delle creazioni, animazione e rendering delle creazioni e così via. Questo richiede molto sia dalla GPU che dalla CPU, quindi abbiamo eseguito molto profiling dei frame in DevTools di Chrome per ottimizzare al massimo queste parti. Sui dispositivi mobili abbiamo deciso di aumentare un po' lo zoom sulle creazioni per non doverle visualizzare tutte contemporaneamente.

Per alcuni dispositivi abbiamo dovuto rivedere e semplificare alcuni degli shader WebGL, ma abbiamo sempre trovato un modo per risolvere il problema e andare avanti.

Supporto di dispositivi non WebGL

Volevamo che il sito fosse utilizzabile anche se il dispositivo del visitatore non supporta WebGL. A volte esistono modi per rappresentare il 3D in modo semplificato utilizzando una soluzione canvas o le funzionalità CSS3D. Purtroppo non abbiamo trovato una soluzione sufficientemente buona per replicare le funzionalità di Crea ed esplora 3D senza utilizzare WebGL.

Per coerenza, lo stile visivo delle creazioni deve essere lo stesso su tutte le piattaforme. Avremmo potuto provare una soluzione 2,5D, ma in questo modo le creazioni avrebbero avuto un aspetto diverso in qualche modo. Inoltre, abbiamo dovuto assicurarci che le creazioni realizzate con la prima versione di Crea con Chrome avessero lo stesso aspetto e funzionassero senza problemi nella nuova versione del sito come nella prima.

La modalità Esplora 2D è ancora accessibile ai dispositivi non WebGL, anche se non puoi creare nuove creazioni o esplorare in 3D. In questo modo, gli utenti possono comunque farsi un'idea della complessità del progetto e di cosa potrebbero creare utilizzando questo strumento se fossero su un dispositivo compatibile con WebGL. Il sito potrebbe non essere così utile per gli utenti senza il supporto di WebGL, ma dovrebbe almeno fungere da teaser e coinvolgerli nel provarlo.

A volte non è possibile mantenere le versioni di riserva per le soluzioni WebGL. Esistono molti motivi possibili: prestazioni, stile visivo, costi di sviluppo e manutenzione e così via. Tuttavia, se decidi di non implementare un piano di riserva, devi almeno occuparti dei visitatori che non supportano WebGL, spiegare perché non possono accedere completamente al sito e fornire istruzioni su come risolvere il problema utilizzando un browser che supporta WebGL.

Gestione patrimoniale

Nel 2013, Google ha introdotto una nuova versione di Google Maps con le modifiche più significative all'interfaccia utente dal suo lancio. Per questo motivo abbiamo deciso di riprogettare Crea con Chrome in modo che si adatti alla nuova interfaccia utente di Google Maps e, nel farlo, abbiamo preso in considerazione altri fattori. Il nuovo design è relativamente piatto, con colori solidi e forme semplici. In questo modo abbiamo potuto utilizzare CSS puro su molti elementi dell'interfaccia utente, riducendo al minimo l'uso delle immagini.

In Esplora dobbiamo caricare molte immagini: miniature per le creazioni, texture delle mappe per le basi e infine le creazioni 3D effettive. Facciamo del nostro meglio per assicurarci che non si verifichino perdite di memoria durante il caricamento costante di nuove immagini.

Le creazioni 3D vengono memorizzate in un formato file personalizzato pacchettizzato come immagine PNG. Mantenendo i dati delle creazioni 3D archiviati come immagine, abbiamo potuto in pratica passare i dati direttamente agli shader che eseguono il rendering delle creazioni.

Per tutte le immagini generate dagli utenti, il design ci ha permesso di utilizzare le stesse dimensioni per tutte le piattaforme, riducendo al minimo lo spazio di archiviazione e l'utilizzo della larghezza di banda.

Gestire l'orientamento dello schermo

È facile dimenticare quanto cambiano le proporzioni dello schermo quando si passa dalla modalità verticale a quella orizzontale e viceversa. Devi tenerne conto fin dall'inizio quando esegui l'adattamento per i dispositivi mobili.

Su un sito web tradizionale con lo scorrimento abilitato, puoi applicare regole CSS per ottenere un sito adattabile che riorganizza i contenuti e i menu. Se puoi utilizzare la funzionalità di scorrimento, il problema è abbastanza gestibile.

Abbiamo utilizzato questo metodo anche con Build, ma le opzioni a nostra disposizione per risolvere il problema del layout erano limitate, perché dovevamo mantenere i contenuti visibili in ogni momento e avere comunque accesso rapido a una serie di controlli e pulsanti. Per i siti di contenuti puri, come i siti di notizie, un layout fluido è molto utile, ma per un'app di giochi come la nostra è stato un problema. È stato difficile trovare un layout che funzionasse sia in orizzontale che in verticale, mantenendo al contempo una buona panoramica dei contenuti e un modo confortevole di interagire. Alla fine abbiamo deciso di mantenere la visualizzazione solo orizzontale e di chiedere all'utente di ruotare il dispositivo.

Esplora è stato molto più facile da risolvere in entrambi gli orientamenti. Per ottenere un'esperienza coerente, è stato sufficiente regolare il livello di zoom del 3D in base all'orientamento.

La maggior parte del layout dei contenuti è controllata da CSS, ma alcuni elementi relativi all'orientamento dovevano essere implementati in JavaScript. Abbiamo riscontrato che non esisteva una buona soluzione cross-device per utilizzare window.orientation per identificare l'orientamento, quindi alla fine abbiamo semplicemente confrontato window.innerWidth e window.innerHeight per identificare l'orientamento del dispositivo.

if( window.innerWidth > window.innerHeight ){
  //landscape
} else {
  //portrait
}

Aggiunta del supporto del tocco

L'aggiunta del supporto tocco ai contenuti web è abbastanza semplice. L'interattività di base, come l'evento di clic, funziona allo stesso modo su computer e dispositivi con tocco, ma per le interazioni più avanzate devi gestire anche gli eventi touch: touchstart, touchmove e touchend. Questo articolo illustra le nozioni di base su come utilizzare questi eventi. Internet Explorer non supporta gli eventi touch, ma utilizza gli eventi del cursore (pointerdown, pointermove, pointerup). Gli eventi del cursore sono stati inviati al W3C per la standardizzazione, ma al momento sono implementati solo in Internet Explorer.

Nella modalità Esplora 3D volevamo la stessa navigazione dell'implementazione standard di Google Maps: usare un dito per spostarsi sulla mappa e due dita per aumentare lo zoom. Poiché le creazioni sono in 3D, abbiamo aggiunto anche il gesto di rotazione con due dita. In genere, questo richiede l'utilizzo di eventi tocco.

È buona prassi evitare calcoli complessi, come l'aggiornamento o il rendering del 3D nei gestori degli eventi. Memorizza invece l'input tocco in una variabile e rispondi all'input nel loop di rendering requestAnimationFrame. In questo modo è anche più facile avere contemporaneamente un'implementazione del mouse: devi solo memorizzare i valori del mouse corrispondenti nelle stesse variabili.

Per iniziare, inizializza un oggetto in cui memorizzare l'input e aggiungi l'ascoltatore di eventi touchstart. In ogni gestore di eventi chiamiamo event.preventDefault(). Questo per impedire al browser di continuare a elaborare l'evento tocco, il che potrebbe causare alcuni comportamenti imprevisti come lo scorrimento o la ridimensionamento dell'intera pagina.

var input = {dragStartX:0, dragStartY:0, dragX:0, dragY:0, dragDX:0, dragDY:0, dragging:false};
plateContainer.addEventListener('touchstart', onTouchStart);

function onTouchStart(event) {
  event.preventDefault();
  if( event.touches.length === 1){
    handleDragStart(event.touches[0].clientX , event.touches[0].clientY);
    //start listening to all needed touchevents to implement the dragging
    document.addEventListener('touchmove', onTouchMove);
    document.addEventListener('touchend', onTouchEnd);
    document.addEventListener('touchcancel', onTouchEnd);
  }
}

function onTouchMove(event) {
  event.preventDefault();
  if( event.touches.length === 1){
    handleDragging(event.touches[0].clientX, event.touches[0].clientY);
  }
}

function onTouchEnd(event) {
  event.preventDefault();
  if( event.touches.length === 0){
    handleDragStop();
    //remove all eventlisteners but touchstart to minimize number of eventlisteners
    document.removeEventListener('touchmove', onTouchMove);
    document.removeEventListener('touchend', onTouchEnd);
    //also listen to touchcancel event to avoid unexpected behavior when switching tabs and some other situations
    document.removeEventListener('touchcancel', onTouchEnd);
  }
}

Non effettuiamo l'archiviazione effettiva dell'input nei gestori degli eventi, ma in gestori separati: handleDragStart, handleDragging e handleDragStop. Questo perché vogliamo poterli chiamare anche dai gestori di eventi del mouse. Tieni presente che, anche se è improbabile, l'utente potrebbe utilizzare contemporaneamente il tocco e il mouse. Invece di gestire direttamente la richiesta, ci assicuriamo che non si verifichino problemi.

function handleDragStart(x ,y ){
  input.dragging = true;
  input.dragStartX = input.dragX = x;
  input.dragStartY = input.dragY = y;
}

function handleDragging(x ,y ){
  if(input.dragging) {
    input.dragDX = x - input.dragX;
    input.dragDY = y - input.dragY;
    input.dragX = x;
    input.dragY = y;
  }
}

function handleDragStop(){
  if(input.dragging) {
    input.dragging = false;
    input.dragDX = 0;
    input.dragDY = 0;
  }
}

Quando si creano animazioni basate su touchmove, è spesso utile memorizzare anche il movimento delta dall'ultimo evento. Ad esempio, lo abbiamo utilizzato come parametro per la velocità della videocamera quando si sposta su tutte le piastre di base in Esplora, poiché non trascini le piastre di base, ma muovi effettivamente la videocamera.

function onAnimationFrame() {
  requestAnimationFrame( onAnimationFrame );

  //execute animation based on input.dragDX, input.dragDY, input.dragX or input.dragY
 /*
  /
  */

  //because touchmove is only fired when finger is actually moving we need to reset the delta values each frame
  input.dragDX=0;
  input.dragDY=0;
}

Esempio incorporato: trascinamento di un oggetto utilizzando gli eventi touch. Implementazione simile a quella utilizzata per trascinare la mappa 3D di Esplora in Crea con Chrome: http://cdpn.io/qDxvo

Gesti multi-touch

Esistono diversi framework o librerie, come Hammer o QuoJS, che possono semplificare la gestione dei gesti multi-touch, ma se vuoi combinare più gesti e avere il controllo completo, a volte è meglio farlo da zero.

Per gestire i gesti di pizzicamento e rotazione, memorizziamo la distanza e l'angolo tra due dita quando il secondo dito viene posizionato sullo schermo:

//variables representing the actual scale/rotation of the object we are affecting
var currentScale = 1;
var currentRotation = 0;

function onTouchStart(event) {
  event.preventDefault();
  if( event.touches.length === 1){
    handleDragStart(event.touches[0].clientX , event.touches[0].clientY);
  }else if( event.touches.length === 2 ){
    handleGestureStart(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY );
  }
}

function handleGestureStart(x1, y1, x2, y2){
  input.isGesture = true;
  //calculate distance and angle between fingers
  var dx = x2 - x1;
  var dy = y2 - y1;
  input.touchStartDistance=Math.sqrt(dx*dx+dy*dy);
  input.touchStartAngle=Math.atan2(dy,dx);
  //we also store the current scale and rotation of the actual object we are affecting. This is needed to support incremental rotation/scaling. We can't assume that an object is always the same scale when gesture starts.
  input.startScale=currentScale;
  input.startAngle=currentRotation;
}

Nell'evento touchmove, misuriamo continuamente la distanza e l'angolo tra le due dita. La differenza tra la distanza iniziale e quella attuale viene utilizzata per impostare la scala, mentre la differenza tra l'angolo iniziale e quello attuale viene utilizzata per impostare l'angolo.

function onTouchMove(event) {
  event.preventDefault();
  if( event.touches.length  === 1){
    handleDragging(event.touches[0].clientX, event.touches[0].clientY);
  }else if( event.touches.length === 2 ){
    handleGesture(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY );
  }
}

function handleGesture(x1, y1, x2, y2){
  if(input.isGesture){
    //calculate distance and angle between fingers
    var dx = x2 - x1;
    var dy = y2 - y1;
    var touchDistance = Math.sqrt(dx*dx+dy*dy);
    var touchAngle = Math.atan2(dy,dx);
    //calculate the difference between current touch values and the start values
    var scalePixelChange = touchDistance - input.touchStartDistance;
    var angleChange = touchAngle - input.touchStartAngle;
    //calculate how much this should affect the actual object
    currentScale = input.startScale + scalePixelChange*0.01;
    currentRotation = input.startAngle+(angleChange*180/Math.PI);
    //upper and lower limit of scaling
    if(currentScale<0.5) currentScale = 0.5;
    if(currentScale>3) currentScale = 3;
  }
}

Potresti potenzialmente utilizzare la variazione di distanza tra ogni evento touchmove in modo simile all'esempio con il trascinamento, ma questo approccio è spesso più utile quando vuoi un movimento continuo.

function onAnimationFrame() {
  requestAnimationFrame( onAnimationFrame );
  //execute transform based on currentScale and currentRotation
  /*
  /
  */

  //because touchmove is only fired when finger is actually moving we need to reset the delta values each frame
  input.dragDX=0;
  input.dragDY=0;
}

Se vuoi, puoi anche attivare il trascinamento dell'oggetto mentre esegui i gesti di pizzicamento e rotazione. In questo caso, utilizzerai il punto centrale tra i due tocchi come input per il gestore del trascinamento.

Esempio incorporato: rotazione e ridimensionamento di un oggetto in 2D. In modo simile a come è implementata la mappa in Esplora: http://cdpn.io/izloq

Supporto di mouse e tocco sullo stesso hardware

Oggi esistono diversi laptop, come Chromebook Pixel, che supportano sia il mouse sia l'input tocco. Se non fai attenzione, questo potrebbe causare alcuni comportamenti imprevisti.

Un aspetto importante è che non devi solo rilevare il supporto del tocco e ignorare l'input del mouse, ma supportare entrambi contemporaneamente.

Se non utilizzi event.preventDefault() nei gestori degli eventi tocco, verranno attivati anche alcuni eventi del mouse emulati, in modo da mantenere in funzione la maggior parte dei siti ottimizzati per il tocco. Ad esempio, per un singolo tocco sullo schermo, questi eventi potrebbero essere attivati in una sequenza rapida e in questo ordine:

  1. touchstart
  2. touchmove
  3. touchend
  4. mouseover
  5. mousemove
  6. mousedown
  7. mouseup
  8. clic

Se hai interazioni un po' più complesse, questi eventi del mouse potrebbero causare un comportamento imprevisto e rovinare l'implementazione. Spesso è preferibile utilizzare event.preventDefault() nei gestori degli eventi tocco e gestire l'input del mouse in gestori degli eventi separati. Tieni presente che l'utilizzo di event.preventDefault() nei gestori degli eventi tocco impedisce anche alcuni comportamenti predefiniti, come lo scorrimento e l'evento di clic.

"In Build with Chrome non volevamo che lo zoom avvenisse quando un utente toccava due volte il sito, anche se questa è una funzionalità standard nella maggior parte dei browser. Pertanto, utilizziamo il meta tag viewport per indicare al browser di non aumentare lo zoom quando un utente esegue un doppio tocco. Viene inoltre rimosso il ritardo del clic di 300 ms, il che migliora la reattività del sito. Il ritardo del clic serve a distinguere tra un singolo tocco e un doppio tocco quando è attivato lo zoom con doppio tocco.

<meta name="viewport" content="width=device-width,user-scalable=no">

Ricorda che, quando utilizzi questa funzionalità, sta a te rendere il sito leggibile su tutte le dimensioni dello schermo, perché l'utente non potrà aumentare lo zoom.

Input da mouse, tocco e tastiera

Nella modalità Esplora 3D volevamo che fossero disponibili tre modi per spostarsi sulla mappa: con il mouse (trascinamento), con il tocco (trascinamento, pizzico per lo zoom e rotazione) e con la tastiera (navigazione con i tasti freccia). Tutti questi metodi di navigazione funzionano in modo leggermente diverso, ma abbiamo utilizzato lo stesso approccio per tutti: impostare le variabili nei gestori degli eventi e intervenire in base a queste nel ciclo requestAnimationFrame. Il loop requestAnimationFrame non deve sapere quale metodo viene utilizzato per la navigazione.

Ad esempio, potremmo impostare il movimento della mappa (dragDX e dragDY) con tutti e tre i metodi di immissione. Ecco l'implementazione della tastiera:

document.addEventListener('keydown', onKeyDown );
document.addEventListener('keyup', onKeyUp );

function onKeyDown( event ) {
  input.keyCodes[ "k" + event.keyCode ] = true;
  input.shiftKey = event.shiftKey;
}

function onKeyUp( event ) {
  input.keyCodes[ "k" + event.keyCode ] = false;
  input.shiftKey = event.shiftKey;
}

//this needs to be called every frame before animation is executed
function handleKeyInput(){
  if(input.keyCodes.k37){
    input.dragDX = -5; //37 arrow left
  } else if(input.keyCodes.k39){
    input.dragDX = 5; //39 arrow right
  }
  if(input.keyCodes.k38){
    input.dragDY = -5; //38 arrow up
  } else if(input.keyCodes.k40){
    input.dragDY = 5; //40 arrow down
  }
}

function onAnimationFrame() {
  requestAnimationFrame( onAnimationFrame );
  //because keydown events are not fired every frame we need to process the keyboard state first
  handleKeyInput();
  //implement animations based on what is stored in input
   /*
  /
  */

  //because touchmove is only fired when finger is actually moving we need to reset the delta values each frame
  input.dragDX = 0;
  input.dragDY = 0;
}

Esempio incorporato: Utilizzo del mouse, del tocco e della tastiera per navigare: http://cdpn.io/catlf

Riepilogo

L'adattamento di Crea con Chrome per supportare i dispositivi touch con molte dimensioni dello schermo diverse è stata un'esperienza di apprendimento. Il team non aveva molta esperienza con questo livello di interattività sui dispositivi touch e abbiamo imparato molto strada facendo.

La sfida più grande è stata capire come risolvere i problemi relativi all'esperienza utente e al design. Le sfide tecniche hanno riguardato la gestione di molti formati dello schermo, eventi tocco e problemi di prestazioni.

Anche se ci sono stati alcuni problemi con gli shader WebGL sui dispositivi touch, il risultato è stato quasi migliore del previsto. I dispositivi sono sempre più potenti e le implementazioni di WebGL stanno migliorando rapidamente. Riteniamo che in futuro utilizzeremo WebGL sui dispositivi molto più spesso.

Ora, se non l'hai ancora fatto, crea qualcosa di fantastico.