Développer un site web unique grâce à pixijs et webgl.

Processus technologique et créatif derrière la grille de projet en page d’accueil de Bien Joué.

Technologie libre de droits

Chez MILL3, nous aimons les technologies open source. Nous utilisons et contribuons à plusieurs projets de ce genre à chaque jour. Chacun d’entre eux nécessite une approche et une solution différentes. C’est pourquoi notre équipe de développeurs expérimentée débute toujours un projet avec une phase d’exploration et d’analyse pour s’assurer d’utiliser la meilleure solution technologique possible. Pour la plateforme web de Bien Joué, nous avons utilisé la librairie PixiJS comme base de programmation de la page d’accueil. Cette approche permet d’intégrer des effets visuels et des animations de grande qualité et fluidité, autant sur un appareil mobile que sur un ordinateur haute performance.

Définir la grille

La grille utilisée pour ce projet est de type maçonnerie (appelée masonry en anglais). La particularité de cette grille est que les éléments sont distribués de gauche à droite, sans restreindre chacun des éléments à une hauteur fixe.

Cette particularité, qui peut sembler simple à première vue, rend l’élaboration d’une telle grille très complexe lorsque nous désirons qu’une ou les deux dimensions de notre grille soient infinies. De plus, comme nous travaillons dans un environnement WebGL, nous ne pouvons utiliser les grilles CSS (css grid) pour faire ce travail.

Comme vous pouvez le voir dans l’image ci-dessus, notre grille contient 5 formats distincts. Chaque format possède un ratio hauteur/largeur prédéfini pour les besoins du projet (1:1, 3:4, 4:3, 9:16, 16:9).

Si l’on décortique le fonctionnement d’une grille masonry, on comprend que la distribution est déterminée selon la colonne qui est la moins remplie. Dans notre exemple à 4 colonnes, chaque colonne est initialement vide (hauteur = 0). Il faut d’abord déterminer dans quelle colonne notre élément sera ajouté. Pour ce faire, il faut trouver quelle colonne est la moins haute. Ensuite, nous ajoutons notre élément à cette colonne et additionnons la hauteur de notre élément à la hauteur de notre colonne (hauteur += élément). Et ainsi de suite jusqu’à ce que la grille soit complète. Voici ce que ça donne en code :

Grille responsive

Une fois notre grille de base en place, il faut qu’elle soit en mesure de s’adapter aux différentes tailles d’écran. De plus, une grille à 4 colonnes sur un écran de téléphone n’est pas optimale. Dans ce cas, nous afficherons 2 colonnes sur les petits écrans, et 4 pour les autres.

Pour ce faire, à chaque fois que la taille de notre fenêtre navigateur change, nous devons :

  1. Déterminer la nouvelle taille de l’écran
  2. Calculer le nombre de colonnes nécessaire selon la largeur de l’écran
  3. Effacer tous les éléments de notre grille
  4. Remplir à nouveau notre grille

NB : Cette technique n’est pas optimale et est utilisée à titre d’exemple seulement. Il est préférable de réutiliser les éléments existants et de les repositionner au lieu de tout détruire et reconstruire.

Naviguer dans la grille

Une fois notre grille en place, il faut pouvoir la déplacer horizontalement et verticalement. Pour ce faire, nous utiliserons deux interfaces différentes : drag & drop et mouse wheel.

Grille infinie à une dimension (verticale)

Une fois que notre grille peut bouger, il faut être en mesure de créer et de supprimer les éléments de notre grille au fur et à mesure que notre grille se déplace dans l’écran. Pour ce faire, nous devrons un peu revoir la façon dont nous gérons notre grille.

Voici comment mettre en place cet algorithme :

1. Déterminer si l’extrémité inférieure du premier élément de chaque colonne est plus petite que zéro. 

Oui :

  • On supprime cet élément.
  • On soustrait la hauteur de cet élément de la hauteur de notre colonne.

Non :

  • Si l’extrémité supérieure du premier élément de chaque colonne est plus grande que zéro :
    • On ajouter un élément au début de cette colonne.
    • On additionne la hauteur de cet élément à la hauteur de notre colonne.

2. Déterminer si l’extrémité supérieure du dernier élément de chaque colonne est plus grande que la hauteur de l’écran.

Oui :

  • On supprime cet élément.
  • On soustrait la hauteur de cet élément de notre colonne.

Non :

  • Si l’extrémité inférieure du dernier élément de chaque colonne est plus petite que la hauteur de l’écran :
    • On ajoute un élément à la fin de cette colonne.
    • On additionne la hauteur de cet élément à la hauteur de notre colonne.

Grille infinie à deux dimensions

Notre grille peut dorénavant bouger à l’infini sur l’axe vertical. Il faut à présent permettre le défilement horizontal. Pour ce faire, nous allons utiliser le même algorithme vertical, en appliquant de légères modifications pour l’adapter à l’axe horizontal.

1. Déterminer si l’extrémité droite de notre première colonne est plus petite que zéro.

Oui :

  • On supprime cette colonne et tous ses éléments.

Non :

  • Si l’extrémité gauche de notre première colonne est plus grande que zéro :
    • On ajoute une colonne au début de notre grille.
    • On ajoute des éléments à cette colonne jusqu’à ce qu’elle remplisse la hauteur de l’écran.

2. Déterminer si l’extrémité gauche de notre dernière colonne est plus grande que la largeur de l’écran.

Oui :

  • On supprime cette colonne et tous ses éléments.

Non :

  • Si l’extrémité droite de notre dernière colonne est plus petite que la largeur de l’écran :
    • On ajoute une colonne à la fin de notre grille.
    • On ajoute des éléments à cette colonne jusqu’à ce qu’elle remplisse la hauteur de l’écran.

Ce qui rend cet algorithme particulier c’est que dorénavant, nous pouvons avoir plus de 4 (ou 2 sur un petit écran) colonnes visibles à l’écran en même temps. Par contre, comme notre algorithme ajoute et supprime automatiquement des éléments à notre grille, le nombre d’éléments à afficher à l’écran est toujours le plus bas possible. Cette approche est primordiale pour avoir un mouvement de grille fluide et performant.

Effets visuels

WebGL nous permet des effets visuels qui ne sont pas possibles uniquement en CSS. Toutefois, il peut être assez complexe de créer des effets visuels sur mesure en WebGL sans utiliser différentes librairies open source. Heureusement pour nous, PixiJS possède une banque d’effets visuels de base qui peuvent se combiner pour donner des résultats très impressionnants.

Parallax

Même s’il est très subtil dans ce projet, un effet de parallaxe ajoute toujours une forte dose de dynamisme à n’importe quel projet. Pour Bien Joué, nous avons opté pour un léger effet parallaxe afin d’augmenter le sentiment de profondeur dans le mouvement de notre grille.

Pour ce faire, nous avons créé un masque (mask) à l’intérieur de chaque élément qui sera appliqué sur notre texture d’aperçu du projet. Ensuite, nous ferons bouger notre texture indépendamment de notre élément.

Distorsion (distortion effects)

Probablement l’effet le plus intéressant du projet, il apporte une touche d’originalité que l’on ne voit pas régulièrement. Pour réaliser cet effet, nous avons créé un filtre personnalisé dans PixiJS avec shader OpenGL. Le code du shader a été inspiré par cette expérimentation : Cubic Lens Distortion Shader.

Flou directionnel (motion blur)

Un flou directionnel est appliqué directement sur le stage via un BlurFilter disponible dans PixiJS. Sa valeur est calculée selon la vitesse de déplacement actuel de la grille. Plus le déplacement est rapide, plus la valeur du flou directionnel sera grande.

Aperçu vidéo

L’intégration vidéo dans PixiJS se fait sans le moindre problème. Il y a cependant deux points à considérer lorsque vous voulez une texture vidéo qui doit apparaître en rollover :

  1. Utiliser une taille vidéo liée à la taille de l’écran. Le chargement de votre vidéo sera plus rapide, utilisera moins de mémoire vive et ne fera pas planter votre application. En d’autres mots, il ne sert à rien de charger une vidéo de 1920×1080 pour les petits écrans
  2. Il doit y avoir au moins un click/tap d’enregistrer avant de pouvoir débuter le téléchargement et la lecture d’une vidéo. Si vous ne respectez pas cette règle, la vidéo ne se lancera jamais.

C’est à cause de ce deuxième point que nous avons ajouté, en lever de rideau, une phrase clé et un bouton Entrer avant l’affichage de la grille interactive.

Affichage d’éléments textes avec PixiJS

Un des inconvénients de WebGL est sa faiblesse dans la gestion des textes. Étant un outil de rastérisation, WebGL n’est pas la meilleure option pour afficher des polices de caractères et de texte, surtout en petite taille.

Nos designers portent une attention très particulière aux choix typographiques de chaque projet. Il était hors de question que le texte sur chaque vignette de la grille ne soit pas lisible. De ce fait, nous avons passé plusieurs heures à expérimenter et tester différentes avenues pour afficher le texte de la façon la plus précise possible. Au final, nous avons opté pour une BitmapFont créée spécifiquement pour les besoins particuliers que nous avions.

Curseur personnalisé

Afin de rendre l’expérience encore plus singulière, nous avons créé un curseur personnalisé laissant plus de place aux éléments de la grille. Le curseur de la souris est remplacé par un simple rond blanc. Lorsque vous survolez une vignette, une flèche stylisée selon la charte graphique du site web remplace le doigt pointeur traditionnel.

Easter Egg

Nous avons ajouté une petite fonction cachée dans la page d’accueil de Bien Joué. L’avez-vous déjà trouvée? Sinon, je vous invite à aller voir le site de Bien Joué et à expérimenter différentes interactions sur la page d’accueil.

Pour déclencher l’ouverture de la démo de Bien Joué, vous devez faire défiler rapidement la grille pendant 3 secondes consécutives.

Consulter le résultat final

Le code complet est disponible sur CodePen.

Vous aimeriez vous joindre à notre équipe?

Envoyez-nous votre cv ou votre profil public GitHub à l’adresse info@mill3.studio. Vous serez peut-être le prochain à rédiger un article sur ce blogue!