Compiler avec Chrome

Les briques LEGO® disponibles sur le Web multi-appareil

Build with Chrome, une expérience amusante pour les utilisateurs de Chrome sur ordinateur lancée à l'origine en Australie, a été republiée en 2014, avec une disponibilité dans le monde entier, des mises en lien avec THE LEGO® MOVIETM et une nouvelle compatibilité avec les appareils mobiles. Dans cet article, nous partagerons certains enseignements tirés du projet, notamment en ce qui concerne le passage d'une expérience basée uniquement sur ordinateur à une solution multi-écran prenant en charge la saisie tactile et à la souris.

L'histoire de Chrome pour créer

La première version de Build with Chrome a été lancée en Australie en 2012. Nous voulions mettre en avant toute la puissance du Web d'une toute nouvelle façon et proposer Chrome à un tout nouveau public.

Le site comportait deux parties principales : le mode "Construire", qui permet aux utilisateurs de réaliser des créations à l'aide de briques LEGO, et le mode "Explorer" pour parcourir les créations sur une version LEGO de Google Maps.

La 3D interactive était essentielle pour offrir aux utilisateurs la meilleure expérience possible en matière de construction LEGO. En 2012, WebGL n'était accessible au public que dans les navigateurs pour ordinateur. Build a donc été ciblé comme une expérience sur ordinateur uniquement. L'outil Explorer a utilisé Google Maps pour afficher les créations. Toutefois, après un zoom suffisamment rapproché, il est passé à une implémentation WebGL de la carte affichant les créations en 3D, mais les cartes Google étaient toujours utilisées comme texture de base. Nous espérions ainsi créer un environnement où les passionnés de LEGO de tous âges pourraient exprimer leur créativité et explorer les créations de leurs camarades de façon simple et intuitive.

En 2013, nous avons décidé d'étendre Build with Chrome à de nouvelles technologies Web. Parmi ces technologies, la technologie WebGL dans Chrome pour Android, qui permettrait naturellement à l'application Build with Chrome de devenir une expérience mobile, Pour commencer, nous avons d'abord développé des prototypes tactiles avant d'interroger le matériel associé à l'outil de création afin de comprendre le comportement et la réactivité tactile des gestes que nous pouvons rencontrer dans un navigateur par rapport à une application mobile.

Une interface réactive

Nous devions prendre en charge les appareils compatibles avec la saisie tactile et à la souris. Cependant, l'utilisation de la même interface utilisateur sur les petits écrans tactiles s'est avérée être une solution non optimale en raison de contraintes d'espace.

L'opération implique de nombreuses interactions: zoom avant et arrière, modification des couleurs des briques, et sélection, rotation et positionnement des briques. Il s'agit d'un outil dans lequel les utilisateurs passent souvent beaucoup de temps. Il est donc important qu'ils aient un accès rapide à tout ce qu'ils utilisent fréquemment et qu'ils doivent pouvoir interagir avec lui.

Lors de la conception d'une application tactile très interactive, vous découvrirez que l'écran semble rapidement petit et que les doigts de l'utilisateur ont tendance à couvrir une grande partie de l'écran lors de l'interaction. Cela est devenu évident pour nous lorsque nous avons travaillé avec Builder. Vous devez vraiment tenir compte de la taille de l'écran physique plutôt que des pixels dans les graphiques lors de la conception. Il est important de réduire le nombre de boutons et de commandes afin de disposer de la plus grande surface possible à l'écran pour le contenu réel.

Notre objectif était de faire en sorte que Build ait l'air naturel sur les appareils tactiles. Il ne s'agissait pas seulement d'ajouter la saisie tactile à l'implémentation d'origine pour ordinateur de bureau, mais aussi de donner l'impression qu'elle était vraiment conçue pour le toucher. Nous avons fini avec deux variantes de l'interface utilisateur, l'une pour les ordinateurs et les tablettes dotées d'un grand écran, et l'autre pour les appareils mobiles dotés d'écrans plus petits. Dans la mesure du possible, il est préférable d'utiliser une seule implémentation et de garantir une transition fluide entre les modes. Dans notre cas, nous avons constaté que l'expérience était tellement différente entre ces deux modes que nous avons décidé d'utiliser un point d'arrêt spécifique. Les deux versions ont beaucoup de fonctionnalités en commun et nous avons essayé de faire la plupart des choses avec une seule implémentation de code, mais certains aspects de l'interface utilisateur fonctionnent différemment entre les deux.

Nous utilisons les données des user-agents pour détecter les appareils mobiles, puis nous vérifions la taille de la fenêtre d'affichage pour décider si l'UI pour mobile à petit écran doit être utilisée. Il est un peu difficile de choisir un point d'arrêt pour ce que devrait être un "grand écran", car il est difficile d'obtenir une valeur fiable de la taille de l'écran physique. Heureusement, dans notre cas, l'affichage de l'UI pour petit écran sur un appareil tactile avec un grand écran n'a pas d'importance, car l'outil fonctionnera toujours, mais certains boutons peuvent sembler un peu trop grands. Au final, nous définissons le point d'arrêt sur 1 000 pixels. Si vous chargez le site à partir d'une fenêtre de plus de 1 000 pixels (en mode Paysage), vous obtiendrez la version grand écran.

Parlons un peu des deux expériences et tailles d'écran:

Grand écran, compatible avec la souris et l'écran tactile

La version grand écran est diffusée sur tous les ordinateurs de bureau compatibles avec la souris et sur les appareils tactiles dotés de grands écrans (tels que le Google Nexus 10). En termes de commandes de navigation disponibles, cette version est proche de la solution d'origine pour ordinateur, mais nous avons ajouté la prise en charge tactile et certains gestes. Nous ajustons l'interface utilisateur en fonction de la taille de la fenêtre. Ainsi, lorsqu'un utilisateur redimensionne la fenêtre, il peut supprimer ou redimensionner une partie de l'interface utilisateur. Pour ce faire, nous utilisons des requêtes média CSS.

Exemple: Lorsque la hauteur disponible est inférieure à 730 pixels, la commande du curseur de zoom en mode Exploration est masquée:

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

Petit écran, commandes tactiles uniquement

Cette version est diffusée sur les appareils mobiles et les petites tablettes (ciblant les appareils Nexus 4 et Nexus 7). Cette version nécessite la compatibilité multipoint.

Sur les appareils à petit écran, nous devons laisser au contenu le plus d'espace possible sur l'écran. Nous avons donc fait quelques ajustements pour maximiser l'espace, principalement en éloignant les éléments rarement utilisés:

  • Le sélecteur de construction est réduit dans un sélecteur de couleur pendant la construction.
  • Nous avons remplacé les commandes de zoom et d'orientation par des gestes à plusieurs doigts.
  • Le mode plein écran de Chrome permet également d'augmenter l'espace disponible sur l'écran.
Créez sur grand écran
Créez des applications sur grand écran Le sélecteur de brique est toujours visible, et quelques commandes se trouvent sur le côté droit.
Créez des applications sur un petit écran
Créez des applications sur un petit écran Le sélecteur de briques a été réduit et certains boutons ont été supprimés.

Performances et compatibilité avec WebGL

Les appareils tactiles modernes disposent de GPU assez puissants, mais ils sont encore loin de ceux de leurs homologues de bureau. Nous savions donc que nous aurions des problèmes de performances, en particulier dans le mode Explorer 3D, qui nécessite d'afficher un grand nombre de créations en même temps.

Nous avons voulu ajouter de nouveaux types de briques aux formes complexes et même transparentes, des caractéristiques généralement très gourmandes en GPU. Cependant, nous devions assurer la rétrocompatibilité et continuer à accepter les créations à partir de la première version. Nous ne pouvions donc pas imposer de nouvelles restrictions, comme une réduction significative du nombre total de briques dans les créations.

Dans la première version de "Construire", le nombre maximal de briques pouvant être utilisées dans une création était limité. Il y avait un « mètre de briques » indiquant le nombre de briques qu'il restait. Dans la nouvelle mise en œuvre, certaines des nouvelles briques ont un impact plus important sur le mètre de briques que sur les briques standards, ce qui réduit légèrement le nombre maximal de briques. C'était une façon d'inclure de nouvelles briques tout en conservant des performances correctes.

En mode Explorer 3D, de nombreuses opérations se produisent en même temps : chargement des textures des plaques, chargements de créations, animations et créations de rendu, etc. Cela nécessite beaucoup de GPU et de processeur. Nous avons donc effectué de nombreux profils de frame dans les outils pour les développeurs Chrome afin d'optimiser ces éléments le plus possible. Sur les appareils mobiles, nous avons décidé de zoomer un peu plus près des créations pour ne pas avoir à afficher autant de créations en même temps.

Certains appareils nous ont demandé de revoir et de simplifier certains nuanceurs WebGL, mais nous avons toujours trouvé un moyen de résoudre ce problème et d'aller plus loin.

Compatibilité avec les appareils non-WebGL

Nous voulions que le site soit plus facile à utiliser même si l'appareil du visiteur n'est pas compatible avec WebGL. Il est parfois possible de représenter la 3D de manière simplifiée à l'aide d'une solution Canevas ou des fonctionnalités CSS3D. Malheureusement, nous n'avons pas trouvé de solution suffisante pour reproduire les fonctionnalités de construction et d'exploration en 3D sans utiliser WebGL.

À des fins de cohérence, le style visuel des créations doit être le même sur toutes les plates-formes. Nous aurions pu essayer une solution 2,5D, mais cela aurait donné un aspect différent à chaque création. Nous avons également dû réfléchir à la façon de nous assurer que les créations conçues avec la première version de Build with Chrome aient le même aspect et fonctionnent aussi bien dans la nouvelle version du site que dans la première.

Le mode Explorer 2D est toujours accessible sur les appareils qui ne disposent pas de la technologie WebGL, même si vous ne pouvez pas créer d'autres créations ni l'explorer en 3D. Ainsi, les utilisateurs peuvent toujours se faire une idée de la profondeur du projet et de ce qu'ils pourraient créer à l'aide de cet outil s'ils se servaient d'un appareil compatible WebGL. Même si le site n'est pas aussi intéressant pour les utilisateurs qui ne sont pas compatibles avec WebGL, il doit au moins servir de teaser et les inciter à l'essayer.

Il est parfois impossible de conserver des versions de remplacement pour les solutions WebGL. Les raisons peuvent être multiples : performances, style visuel, coûts de développement et de maintenance, etc. Toutefois, lorsque vous décidez de ne pas implémenter une création de remplacement, vous devez au moins vous occuper des visiteurs qui n'utilisent pas WebGL, leur expliquer pourquoi ils ne peuvent pas accéder à la totalité du site et leur expliquer comment résoudre le problème à l'aide d'un navigateur compatible avec WebGL.

Gestion des actifs

En 2013, Google a lancé une nouvelle version de Google Maps comportant les modifications les plus importantes de l'interface utilisateur depuis son lancement. Nous avons donc décidé de repenser Build with Chrome pour l'adapter à la nouvelle interface utilisateur de Google Maps, en tenant compte d'autres facteurs. La nouvelle interface est relativement plate, avec des couleurs unies et des formes simples. Cela nous a permis d'utiliser du code CSS pur sur un grand nombre d'éléments de l'interface utilisateur, ce qui a réduit l'utilisation d'images.

Dans l'exploration, nous devons charger un grand nombre d'images : des vignettes pour les créations, des textures de carte pour les plaques et enfin les créations 3D. Lorsque nous chargeons de nouvelles images en permanence, nous veillons tout particulièrement à ce qu'il n'y ait pas de fuite de mémoire.

Les créations 3D sont stockées dans un format de fichier personnalisé empaqueté sous la forme d'une image PNG. Le stockage des données des créations 3D sous forme d'image nous a permis de les transmettre directement aux nuanceurs qui rendent les créations.

La conception nous a permis d'utiliser les mêmes tailles d'image sur toutes les plates-formes pour toutes les images générées par les utilisateurs, ce qui réduit l'utilisation de l'espace de stockage et de la bande passante.

Gérer l'orientation de l'écran

Il est facile d'oublier à quel point le format de l'écran change lorsque vous passez du mode portrait au mode paysage ou inversement. Vous devez en tenir compte dès le départ lorsque vous adaptez votre application aux appareils mobiles.

Sur un site Web traditionnel avec le défilement activé, vous pouvez appliquer des règles CSS pour obtenir un site responsif qui réorganise le contenu et les menus. Tant que vous pouvez utiliser la fonctionnalité de défilement, c'est assez gérable.

Nous avons également utilisé cette méthode avec Build, mais nous étions un peu limités dans la résolution de la mise en page, car nous devions rendre le contenu visible à tout moment et pouvoir accéder rapidement à un certain nombre de commandes et de boutons. Pour les sites de contenu pur, comme les sites d'actualités, une mise en page fluide est tout à fait logique, mais pour une application de jeu comme la nôtre, cela a été difficile. Il est devenu difficile de trouver une mise en page qui fonctionnait à la fois en mode paysage et en mode portrait tout en conservant un bon aperçu du contenu et une façon d'interagir confortablement. Nous avons finalement décidé de laisser le build en mode paysage uniquement et nous avons demandé à l'utilisateur de faire pivoter son appareil.

La réponse à la question "Explorer" a été beaucoup plus facile à résoudre dans les deux sens. Il nous suffit d'ajuster le niveau de zoom de la 3D en fonction de l'orientation pour offrir une expérience cohérente.

La mise en page du contenu est en grande partie contrôlée par CSS, mais certains éléments liés à l'orientation devaient être implémentés en JavaScript. Nous avons constaté qu'il n'y avait pas de bonne solution inter-appareil pour utiliser window.orientation pour identifier l'orientation. Au final, nous avons simplement comparé window.innerWidth et window.innerHeight pour identifier l'orientation de l'appareil.

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

Ajouter une assistance tactile

L'ajout d'une fonctionnalité tactile à un contenu Web est relativement simple. L'interactivité de base, comme l'événement de clic, fonctionne de la même manière sur les ordinateurs et sur les appareils tactiles, mais lorsqu'il s'agit d'interactions plus avancées, vous devez également gérer les événements tactiles : "touchstart", "touchmove" et "touchend". Consultez cet article pour découvrir les principes de base de l'utilisation de ces événements. Internet Explorer n'accepte pas les événements tactiles, mais utilise à la place les événements de pointeur (pointerdown, pointermove, pointer up). Les événements de pointeur ont été envoyés au W3C pour standardisation, mais ils ne sont pour l'instant implémentés que dans Internet Explorer.

En mode Explorer 3D, nous voulions bénéficier de la même navigation que celle de la mise en œuvre standard de Google Maps : un doigt pour faire un panoramique sur la carte et deux doigts pour zoomer. Comme les créations sont en 3D, nous avons également ajouté le geste de rotation avec deux doigts. Cela nécessite généralement l'utilisation d'événements tactiles.

Une bonne pratique consiste à éviter les calculs complexes, tels que la mise à jour ou l'affichage de la 3D dans les gestionnaires d'événements. Stockez plutôt l'entrée tactile dans une variable et réagissez sur l'entrée dans la boucle de rendu requestAnimationFrame. Cela facilite également l'implémentation de la souris en même temps, vous stockez simplement les valeurs de souris correspondantes dans les mêmes variables.

Commencez par initialiser un objet dans lequel stocker l'entrée, puis ajoutez l'écouteur d'événements "touchstart". Dans chaque gestionnaire d'événements, nous appelons event.preventDefault(). Cela permet d'empêcher le navigateur de continuer à traiter l'événement tactile, ce qui peut entraîner un comportement inattendu, tel que le défilement ou la mise à l'échelle de la page entière.

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);
  }
}

Nous ne stockons pas l'entrée dans les gestionnaires d'événements, mais dans des gestionnaires distincts: handleDragStart, handleDragging et handleDragStop. C'est parce que nous voulons aussi pouvoir les appeler à partir des gestionnaires d'événements de souris. Bien que cela soit peu probable, n'oubliez pas que l'utilisateur peut utiliser simultanément l'écran tactile et la souris. Plutôt que de traiter cette demande directement, nous nous assurons simplement que rien n'explose.

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;
  }
}

Lorsque vous créez des animations basées sur des mouvements tactiles, il est souvent utile de stocker également le déplacement delta depuis le dernier événement. Par exemple, nous l'avons utilisé comme paramètre pour la vitesse de la caméra lors des déplacements sur toutes les plaques de base dans Explorer, puisque vous déplacez la caméra non pas les plaques de base.

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;
}

Exemple intégré:faire glisser un objet à l'aide d'événements tactiles. Implémentation semblable à celle utilisée pour faire glisser la carte 3D dans Build with Chrome: http://cdpn.io/qDxvo.

Gestes multipoint

Plusieurs frameworks ou bibliothèques, tels que Hammer ou QuoJS, peuvent se charger de simplifier la gestion des gestes à plusieurs doigts. Toutefois, si vous souhaitez combiner plusieurs gestes et obtenir un contrôle total, il est parfois préférable de le faire en partant de zéro.

Pour gérer les gestes de pincement et de rotation, nous enregistrons la distance et l'angle entre deux doigts lorsque le deuxième doigt est affiché à l'écran:

//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;
}

Lors de l'événement "touchmove", nous mesurons en continu la distance et l'angle entre ces deux doigts. La différence entre la distance de départ et la distance actuelle est ensuite utilisée pour définir l'échelle, tandis que la différence entre l'angle de début et l'angle actuel est utilisée pour définir l'angle.

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;
  }
}

Vous pouvez potentiellement utiliser le changement de distance entre chaque événement tactile de la même manière que dans l'exemple du déplacement, mais cette approche est souvent plus utile lorsque vous souhaitez un mouvement continu.

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;
}

Si vous le souhaitez, vous pouvez également activer le déplacement de l'objet tout en effectuant des gestes de pincement et de rotation. Dans ce cas, vous devez utiliser le point central entre les deux doigts comme valeur d'entrée pour le gestionnaire de déplacement.

Exemple intégré:rotation et mise à l'échelle d'un objet en 2D. Pour l'implémentation de la carte dans Explorer: http://cdpn.io/izloq

Compatibilité avec la souris et le toucher sur le même matériel

Aujourd'hui, il existe plusieurs ordinateurs portables, comme le Chromebook Pixel, compatibles avec la souris et la saisie tactile. Si vous n'y faites pas attention, cela peut entraîner des comportements inattendus.

Il est important de noter que vous ne devez pas simplement détecter les fonctionnalités tactiles et ignorer les entrées de la souris. Vous devez également prendre en charge les deux en même temps.

Si vous n'utilisez pas event.preventDefault() dans vos gestionnaires d'événements tactiles, certains événements de souris émulés seront également déclenchés, afin que la plupart des sites non optimisés pour l'écran tactile continuent de fonctionner. Par exemple, lorsqu'un utilisateur appuie une fois sur l'écran, ces événements peuvent être déclenchés en séquence rapide et dans l'ordre suivant:

  1. CANNOT TRANSLATE
  2. Touchmove
  3. Touchend
  4. survol avec la souris
  5. mousemove
  6. souris
  7. souris
  8. click

Si vos interactions sont un peu plus complexes, ces événements de souris peuvent entraîner un comportement inattendu et perturber votre implémentation. Il est souvent préférable d'utiliser event.preventDefault() dans les gestionnaires d'événements tactiles et de gérer les entrées de la souris dans des gestionnaires d'événements distincts. Sachez que l'utilisation de event.preventDefault() dans les gestionnaires d'événements tactiles empêche également certains comportements par défaut, tels que le défilement et l'événement de clic.

"Dans Build with Chrome, nous ne voulions pas que l'utilisateur doive zoomer lorsqu'un utilisateur appuie deux fois sur le site, alors que cela est courant dans la plupart des navigateurs. Nous utilisons donc la balise Meta de la fenêtre d'affichage pour indiquer au navigateur de ne pas zoomer lorsqu'un utilisateur appuie deux fois. Cela supprime également le délai de clic de 300 ms, ce qui améliore la réactivité du site. (Le délai de clic permet de distinguer entre un appui simple et un double appui lorsque le zoom en appuyant deux fois est activé.)

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

N'oubliez pas que lorsque vous utilisez cette fonctionnalité, il vous appartient de rendre le site lisible sur toutes les tailles d'écran, car l'utilisateur ne pourra pas zoomer de plus près.

Saisie tactile, souris et clavier

En mode Explorer 3D, nous voulions proposer trois façons de naviguer sur la carte: avec la souris (faire glisser), au toucher (faire glisser, pincer pour zoomer et faire pivoter) et avec le clavier (naviguer à l'aide des touches fléchées). Toutes ces méthodes de navigation fonctionnent un peu différemment, mais nous avons utilisé la même approche pour toutes : définir des variables dans les gestionnaires d'événements et agir en conséquence dans la boucle requestAnimationFrame. La boucle requestAnimationFrame n'a pas besoin de savoir quelle méthode est utilisée pour naviguer.

Par exemple, nous pourrions définir le mouvement de la carte (glisserDX et dragDY) avec les trois méthodes de saisie. Voici l'implémentation du clavier:

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;
}

Exemple intégré:navigation avec la souris, le toucher et le clavier: http://cdpn.io/catlf

Résumé

Adapter Build with Chrome aux appareils tactiles avec différentes tailles d'écran a été une expérience enrichissante. L'équipe n'avait pas beaucoup d'expérience dans ce niveau d'interactivité sur les appareils tactiles et nous avons beaucoup appris en cours de route.

Le plus grand défi s'est avéré : comment résoudre l'expérience utilisateur et la conception. Les défis techniques consistaient à gérer de nombreuses tailles d'écran, des événements tactiles et des problèmes de performances.

Même si les nuanceurs WebGL étaient problématiques sur les appareils tactiles, c'est quelque chose qui fonctionnait presque mieux que prévu. Les appareils sont de plus en plus puissants, et les implémentations WebGL s'améliorent rapidement. Nous pensons que nous allons très prochainement utiliser WebGL sur les appareils.

Si vous ne l'avez pas encore fait, créez quelque chose d'exceptionnel !