Crea con Chrome

Il lancio dei mattoncini LEGO® sul web multi-dispositivo

Hans Eklund
Hans Eklund

Build with Chrome, un divertente esperimento per gli utenti di Chrome su computer lanciato inizialmente in Australia, è stato ripubblicato nel 2014 e prevedeva la disponibilità globale, i legami con THE LEGO® MovieTM e il supporto appena aggiunto per i dispositivi mobili. In questo articolo condivideremo alcune nozioni apprese dal progetto, in particolare per quanto riguarda il passaggio dall'esperienza solo da computer a una soluzione multischermo che supporta sia l'input del mouse che quello del tocco.

La storia di Build with Chrome

La prima versione di Build with 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 conteneva due parti principali: la modalità "Costruisci" che permette agli utenti di realizzare creazioni utilizzando i mattoncini LEGO e la modalità "Esplora" per sfogliare le creazioni in una versione di Google Maps basata su LEGO.

Il 3D interattivo è stato essenziale per offrire agli utenti la migliore esperienza di costruzione LEGO. Nel 2012, WebGL era disponibile al pubblico solo nei browser desktop, quindi Build è stata scelta come target solo per desktop. Esplora ha utilizzato Google Maps per visualizzare le creazioni, ma quando ha aumentato lo zoom è passata all'implementazione WebGL della mappa che mostra le creazioni in 3D, utilizzando ancora Google Maps come texture della piastra di base. Speravamo di creare un ambiente in cui gli appassionati di LEGO di tutte le età potessero esprimere in modo facile e intuitivo la loro 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 avrebbe permesso a Build with Chrome di evolversi in un'esperienza mobile. Per iniziare, abbiamo sviluppato prototipi tattili prima di mettere in discussione l'hardware dello "Strumento di creazione" per comprendere il comportamento dei gesti e la reattività tattile che potremmo rilevare in un browser rispetto a un'app mobile.

Un frontend adattabile

Dovevamo supportare i dispositivi con input sia tocco che mouse. Tuttavia, l'utilizzo della stessa UI su touchscreen di dimensioni ridotte si è rivelata una soluzione non ottimale a causa dei limiti di spazio.

In Build c'è molta interattività: aumentare e diminuire lo zoom, cambiare i colori dei mattoni e, naturalmente, selezionare, ruotare e posizionare i mattoni. È uno strumento in cui gli utenti spesso trascorrono molto tempo, quindi è importante che gli utenti possano accedere rapidamente a tutto ciò che usano di frequente e che siano pronti a interagire con essi.

Durante la progettazione di un'applicazione touch altamente interattiva, scoprirai che lo schermo appare rapidamente piccolo e che le dita dell'utente tendono a coprire molto lo schermo durante l'interazione. Questo è diventato evidente per noi quando abbiamo lavorato con Builder. Quando si progetta, occorre considerare le dimensioni fisiche dello schermo piuttosto che i pixel della grafica. È importante ridurre al minimo il numero di pulsanti e controlli in modo da dedicare quanto più spazio possibile sullo schermo ai contenuti effettivi.

Il nostro obiettivo era fare in modo che Build risulti naturale sui dispositivi tattili, non solo aggiungendo l'input tocco all'implementazione desktop originale, ma anche in modo che appaia come realmente destinato al tocco. Abbiamo ottenuto due varianti dell'UI: una per computer e tablet con schermi grandi e un'altra per dispositivi mobili con schermi più piccoli. Laddove possibile, ti consigliamo di utilizzare un'unica implementazione e di avere una transizione fluida tra le modalità. Nel nostro caso, abbiamo stabilito che c'era una differenza 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 provato a fare la maggior parte delle cose con un'unica implementazione del codice, ma alcuni aspetti dell'interfaccia utente funzionano in modo diverso tra le due.

Utilizziamo i dati dello user agent per rilevare i dispositivi mobili, quindi verifichiamo le dimensioni dell'area visibile per decidere se utilizzare l'interfaccia utente mobile con schermo piccolo. È un po' difficile scegliere un punto di interruzione per uno schermo di grandi dimensioni, perché è difficile ottenere un valore affidabile per le dimensioni fisiche dello schermo. Fortunatamente, nel nostro caso non è importante visualizzare l'interfaccia utente a schermo piccolo su un dispositivo touch con uno schermo grande, perché lo strumento continuerà a funzionare correttamente, ma solo che alcuni pulsanti potrebbero sembrare un po' troppo grandi. Alla fine, impostiamo il punto di interruzione su 1000 pixel; se carichi il sito da una finestra più larga di 1000 pixel (in modalità Orizzontale), otterrai la versione su schermo grande.

Parliamo un po' delle due dimensioni degli schermi e delle diverse esperienze:

Ampio schermo con supporto per mouse e tocco

La versione con schermo grande viene fornita su tutti i computer che supportano il mouse e sui dispositivi tattili con schermi di grandi dimensioni (come il Google Nexus 10). Questa versione è simile alla soluzione desktop originale per il tipo di controlli di navigazione disponibili, ma abbiamo aggiunto il supporto touch e alcuni gesti. Modifichiamo l'interfaccia utente in base alle dimensioni della finestra, quindi quando un utente ridimensiona la finestra, potrebbe rimuoverla o ridimensionarne parte. A tal fine, utilizziamo le query supporti CSS.

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

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

Schermo piccolo, solo supporto touch

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 lasciare ai contenuti quanto più spazio possibile sullo schermo, quindi abbiamo apportato alcune modifiche per massimizzare lo spazio, principalmente spostando gli elementi che usi di rado al di fuori:

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

Prestazioni e supporto di WebGL

I moderni dispositivi touch hanno GPU abbastanza potenti, ma sono ancora lontani dalle loro controparti desktop, quindi sapevamo che avremmo avuto alcune sfide con le prestazioni, soprattutto nella modalità Esplora 3D, dove dobbiamo eseguire il rendering di molte creazioni contemporaneamente.

A livello creativo, volevamo aggiungere un paio di nuovi tipi di mattoncini con forme complesse e persino trasparenza, caratteristiche che in genere sono molto pesanti sulla GPU. Tuttavia, dovevamo essere compatibili con le versioni precedenti e continuare a supportare le creazioni della prima versione, quindi non potevamo impostare nuove restrizioni, come una riduzione significativa del numero totale di mattoni nelle creazioni.

Nella prima versione di Build avevamo un limite massimo di mattoncini utilizzabili in una singola creazione. C'era un "metro di mattoni" che indicava quanti mattoni erano rimasti. Nella nuova implementazione, alcuni dei nuovi mattoncini incidevano maggiormente sul metro di mattoncini rispetto ai mattoncini standard, riducendo così il numero massimo totale di mattoni. Questo era un modo per includere i nuovi mattoni, mantenendo al contempo prestazioni soddisfacenti.

In modalità Esplora 3D sono in corso molte cose contemporaneamente: caricamento di texture della piastra di base, caricamento delle creazioni, animazione e rendering delle creazioni e così via. Questo richiede molto sia GPU che CPU, quindi abbiamo eseguito un'elevata profilazione dei frame in Chrome DevTools per ottimizzare il più possibile queste parti. Sui dispositivi mobili abbiamo deciso di avvicinare un po' di più le creazioni in modo da non dover visualizzare contemporaneamente tante creazioni.

Alcuni dispositivi ci hanno richiesto di rivedere e semplificare alcuni degli Shaper WebGL, ma abbiamo sempre trovato un modo per risolvere il problema e andare avanti.

Supporto di dispositivi non WebGL

Volevamo che il sito fosse abbastanza 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. Sfortunatamente, non siamo riusciti a trovare una soluzione adeguata per replicare le funzionalità di Build ed Explore 3D senza utilizzare WebGL.

Per coerenza, lo stile visivo delle creazioni deve essere lo stesso su tutte le piattaforme. Potenzialmente, avremmo potuto provare una soluzione 2.5D, ma questo avrebbe reso le creazioni in qualche modo diverse. Abbiamo anche valutato come assicurarci che le creazioni realizzate con la prima versione di Build with Chrome avrebbero avuto lo stesso aspetto e la stessa fluidità della 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 profondità del progetto e di cosa potrebbero creare utilizzando questo strumento se utilizzassero un dispositivo abilitato per WebGL. Il sito potrebbe non essere così utile per gli utenti che non supportano WebGL, ma dovrebbe fungere almeno da teaser e coinvolgerli nel provarlo.

A volte non è possibile mantenere versioni di riserva per le soluzioni WebGL. I motivi possono essere diversi: prestazioni, stile visivo, costi di sviluppo e manutenzione e così via. Tuttavia, se decidi di non implementare un elemento di riserva, devi almeno occuparti dei visitatori che non utilizzano WebGL, spiegare perché non possono accedere completamente al sito e fornire istruzioni su come possono risolvere il problema utilizzando un browser che supporti 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. Abbiamo quindi deciso di riprogettare Build with Chrome per adattarlo alla nuova interfaccia utente di Google Maps e, nel frattempo, abbiamo preso altri fattori nella riprogettazione. Il nuovo design è relativamente piatto, con colori a tinta unita puliti e forme semplici. Questo ci ha permesso di utilizzare CSS puri 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 placche di base e infine le vere e proprie creazioni 3D. Facciamo molta attenzione affinché non vi siano perdite di memoria quando carichiamo costantemente nuove immagini.

Le creazioni in 3D vengono archiviate in un formato file personalizzato pacchettizzato come immagine PNG. Conservare i dati delle creazioni 3D memorizzati sotto forma di immagine ci ha permesso di passare sostanzialmente i dati direttamente agli shabby che eseguivano il rendering delle creazioni.

Il design di tutte le immagini generate dagli utenti ci ha consentito di utilizzare le stesse dimensioni delle immagini su tutte le piattaforme, riducendo così al minimo l'utilizzo dello spazio di archiviazione e della larghezza di banda.

Gestione dell'orientamento dello schermo

È facile dimenticare quanto cambiano le proporzioni dello schermo quando si passa dalla modalità verticale a quella orizzontale o viceversa. Devi considerare questo aspetto sin dall'inizio quando ti adatti ai dispositivi mobili.

Su un sito web tradizionale con lo scorrimento attivato, puoi applicare regole CSS per creare un sito adattabile che riordina i contenuti e i menu. È sufficiente utilizzare la funzionalità di scorrimento.

Abbiamo utilizzato questo metodo anche con Build, ma avevamo un po' di limitazioni nel modo in cui potevamo risolvere il layout, perché dovevamo che i contenuti fossero sempre visibili e che avessero comunque accesso rapido a una serie di controlli e pulsanti. Per i siti di contenuti semplici come i siti di notizie, un layout fluido è molto logico, ma per un'app di gioco come la nostra è stato difficile. Non è stato facile trovare un layout che funzionasse sia con l'orientamento orizzontale che verticale, garantendo al contempo una buona panoramica dei contenuti e un modo confortevole di interagire. Alla fine, abbiamo deciso di mantenere Build solo in orizzontale e abbiamo chiesto all'utente di ruotare il dispositivo.

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

La maggior parte del layout dei contenuti è controllata da CSS, ma alcuni elementi relativi all'orientamento dovevano essere implementati in JavaScript. Abbiamo scoperto 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 touch

L'aggiunta del supporto touch ai contenuti web è ragionevolmente semplice. L'interattività di base, ad esempio l'evento di clic, funziona allo stesso modo su computer e dispositivi abilitati al tocco, ma quando si tratta di interazioni più avanzate devi anche gestire gli eventi touch: touchstart, touchmove e touchend. Questo articolo illustra le nozioni di base sull'utilizzo di questi eventi. Internet Explorer non supporta gli eventi tocco, ma utilizza invece gli eventi puntatore (pointerdown, cursormove, cursorup). Gli eventi Pointer sono stati inviati a W3C per la standardizzazione, ma per il momento vengono implementati solo in Internet Explorer.

Nella modalità Esplora 3D volevamo la stessa navigazione dell'implementazione standard di Google Maps: utilizzava un dito per spostarti sulla mappa e pizzica lo schermo con due dita per eseguire lo zoom. Poiché le creazioni sono in 3D, abbiamo aggiunto anche il gesto di rotazione con due dita. In genere si tratta di un evento che richiede l'uso degli eventi tocco.

È buona norma evitare l'esecuzione di operazioni complicate, come l'aggiornamento o il rendering del 3D nei gestori di eventi. Archivia invece l'input tocco in una variabile e reagisci all'input nel loop di rendering requestAnimationFrame. In questo modo è anche più facile implementare contemporaneamente il mouse, poiché devi solo archiviare i valori corrispondenti del mouse nelle stesse variabili.

Inizia inizializzando un oggetto in cui archiviare l'input e aggiungi il listener di eventi touchstart. In ogni gestore di eventi chiamiamo event.preventDefault(). Questo impedisce al browser di continuare a elaborare l'evento touch, il che potrebbe causare comportamenti imprevisti, come lo scorrimento o la scalabilità 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 stiamo memorizzando l'input nei gestori di eventi, ma in gestori separati: handleTrascinaStart, handleTrascinaging e handleTrascinaStop. Questo perché vogliamo essere in grado di chiamarli anche dai gestori di eventi del mouse. Tieni presente che, anche se è improbabile, l'utente può utilizzare tocco e mouse contemporaneamente. Anziché gestire direttamente il caso, ci accertiamo solo che non faccia esplodere nulla.

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 crei animazioni basate su touchmove, spesso è utile memorizzare anche il movimento delta dall'ultimo evento. Ad esempio, abbiamo utilizzato questo parametro come parametro per la velocità della videocamera quando ci si sposta tra tutte le piastre di base in Esplora, dato che non stai trascinando le piastre di base, ma stai effettivamente spostando 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 mediante eventi tocco. Un'implementazione simile a quella utilizzata per trascinare la mappa Esplora 3D in Build with 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 pieno controllo, a volte è meglio farlo da zero.

Per gestire i gesti di pizzicatura 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, quindi, misuriamo continuamente la distanza e l'angolo tra queste 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 l'angolo corrente 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;
  }
}

In teoria, potresti utilizzare la variazione della distanza tra ogni evento touchmove come indicato nell'esempio del 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;
}

Puoi anche attivare il trascinamento dell'oggetto mentre esegui i gesti di pizzicatura e rotazione. In questo caso, devi utilizzare il punto centrale tra le due dita come input per il gestore di trascinamento.

Esempio incorporato: rotazione e ridimensionamento di un oggetto in 2D. In modo simile all'implementazione della mappa in Esplora: http://cdpn.io/izloq

Supporto di mouse e tocco sullo stesso hardware

Oggi ci sono diversi laptop, come il Chromebook Pixel, che supportano sia l'input del mouse sia quello del tocco. Se non fai attenzione, potrebbero verificarsi comportamenti imprevisti.

Una cosa importante è non solo rilevare il supporto touch e ignorare l'input del mouse, ma supportarle contemporaneamente.

Se non usi event.preventDefault() nei gestori di eventi touch, verranno attivati anche alcuni eventi del mouse emulati, per far funzionare la maggior parte dei siti non ottimizzati per il tocco. Ad esempio, per un singolo tocco sullo schermo, questi eventi possono essere attivati in rapida sequenza e in questo ordine:

  1. touchstart
  2. movimento tocco
  3. contatto
  4. mouseover
  5. mousemove
  6. mousedown
  7. mouseup
  8. clic

Se hai interazioni un po' più complesse, questi eventi del mouse possono causare un comportamento imprevisto e compromettere l'implementazione. Spesso è preferibile usare event.preventDefault() nei gestori di eventi touch e gestire l'input del mouse in gestori di eventi separati. Tieni presente che l'uso di event.preventDefault() nei gestori di eventi touch impedirà anche alcuni comportamenti predefiniti, come lo scorrimento e l'evento di clic.

"In Build with Chrome non volevamo che lo zoom si verificasse quando qualcuno toccava due volte il sito, anche se si tratta di un comportamento standard nella maggior parte dei browser. Quindi, usiamo il meta tag dell'area visibile per indicare al browser di non eseguire lo zoom quando un utente tocca due volte. In questo modo viene rimosso anche il ritardo di clic di 300 ms, che migliora la reattività del sito. Il ritardo del clic serve a distinguere tra un tocco singolo 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 funzione spetta a te rendere il sito leggibile su schermi di tutte le dimensioni, in quanto l'utente non sarà in grado di aumentare lo zoom.

Inserimento mouse, tocco e tastiera

In modalità Esplora 3D volevamo avere tre modi per navigare nella mappa: mouse (trascinamento), tocco (trascinamento, pizzica per eseguire lo zoom e rotazione) e 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 di eventi e intervenire nel loop requestAnimationFrame. Il loop requestAnimationFrame non deve necessariamente sapere quale metodo viene utilizzato per navigare.

Ad esempio, possiamo 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: utilizzando mouse, tocco e tastiera per navigare: http://cdpn.io/catlf

Riepilogo

L'adattamento di Build con Chrome in modo da supportare i dispositivi touch con schermi di diverse dimensioni è stata un'esperienza di apprendimento. Il team non aveva molta esperienza nello svolgimento di questo livello di interattività sui dispositivi tattili e lungo il percorso abbiamo imparato molto.

La sfida più grande si è rivelata essere la soluzione per migliorare l'esperienza utente e il design. Le sfide tecniche erano la gestione di schermi di molte dimensioni, eventi tattili e problemi di prestazioni.

Nonostante si siano verificati alcuni problemi con gli ombreggiatori WebGL sui dispositivi touch, si tratta di un aspetto che ha funzionato quasi meglio del previsto. I dispositivi stanno diventando sempre più potenti e le implementazioni WebGL stanno migliorando rapidamente. Riteniamo che nel prossimo futuro utilizzeremo molto più WebGL su dispositivi.

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