Catégories
Astuces et Design

Création de composants d'interface utilisateur en SVG

Je suis fermement convaincu que SVG ouvre tout un monde de création d’interfaces sur le Web. Cela peut sembler intimidant d'apprendre le SVG au début, mais vous avez une spécification conçue pour créer des formes et qui dispose encore d'éléments, tels que du texte, des liens et des étiquettes aria. Vous pouvez obtenir certains des mêmes effets en CSS, mais c'est un peu plus particulier pour obtenir un positionnement parfait, en particulier dans les fenêtres et pour un développement réactif.

La particularité du SVG est que tout le positionnement est basé sur un système de coordonnées, un peu comme le jeu Bataille navale. Cela signifie que décider où tout va et comment il est dessiné, ainsi que comment il est relatif les uns aux autres, peut être très simple à raisonner. Le positionnement CSS est pour la mise en page, ce qui est génial car vous avez des choses qui correspondent les unes aux autres en termes de flux du document. Ce trait par ailleurs positif est plus difficile à utiliser si vous créez un composant très particulier, avec des éléments superposés et placés avec précision.

Vraiment, une fois que vous avez appris SVG, vous pouvez dessiner n'importe quoi et le mettre à l'échelle sur n'importe quel appareil. Même ce site utilise SVG pour les éléments d'interface utilisateur personnalisés, tels que mon avatar, ci-dessus (méta!).

Ce petit demi-cercle sous l'image de l'auteur n'est que du balisage SVG.

Nous ne couvrirons pas tout sur les SVG dans cet article (vous pouvez apprendre quelques-uns de ces principes fondamentaux ici, ici, ici et ici), mais afin d'illustrer les possibilités que SVG ouvre pour le développement de composants d'interface utilisateur, parlons d'un cas d'utilisation particulier et expliquez comment nous penserions à construire quelque chose de personnalisé.

le composant de liste de tâches chronologique

Récemment, je travaillais sur un projet avec mon équipe chez Netlify. Nous voulions montrer au spectateur quelle vidéo d'une série de vidéos dans un cours il regardait actuellement. En d'autres termes, nous voulions créer une sorte de chose qui ressemble à une liste de tâches, mais qui montre la progression globale à mesure que les éléments sont terminés. (Nous avons créé une plate-forme d'apprentissage sur le thème de l'espace libre et c'est super cool. Oui, j'ai dit bonjour.)

Voici à quoi cela ressemble:

Alors, comment procéderions-nous? Je vais montrer un exemple à la fois dans Vue et React afin que vous puissiez voir comment cela pourrait fonctionner dans les deux frameworks.

le Version Vue

Nous avons décidé de créer la plate-forme dans Next.js à des fins de dogfood (c'est-à-dire d'essayer notre propre plugin de construction Next sur Netlify), mais je parle plus couramment Vue, j'ai donc écrit le prototype initial dans Vue et l'ai porté sur React.

Voici la démo complète de CodePen:

Passons un peu en revue ce code. Tout d'abord, il s'agit d'un composant de fichier unique (SFC), de sorte que le modèle HTML, le script réactif et les styles étendus sont tous encapsulés dans ce fichier unique.

Nous stockerons certaines tâches factices dans data, y compris si chaque tâche est terminée ou non. Nous allons également créer une méthode que nous pouvons appeler une directive de clic afin que nous puissions basculer si l'état est terminé ou non.


Maintenant, ce que nous voulons faire est de créer un SVG qui a un flexible viewBox en fonction de la quantité d'éléments. Nous voulons également dire aux lecteurs d'écran qu'il s'agit d'un élément de présentation et que nous fournirons un titre avec un identifiant unique de timeline. (Obtenez plus d'informations sur la création de SVG accessibles.)

le stroke est réglé sur currentColor pour permettre une certaine flexibilité – si nous voulons réutiliser le composant à plusieurs endroits, il héritera de tout color est utilisé sur le div encapsulant.

Ensuite, à l'intérieur du SVG, nous voulons créer une ligne verticale correspondant à la longueur de la liste des tâches. Les lignes sont assez simples. On a x1 et x2 valeurs (où la ligne est tracée sur l'axe des x), et de même, y1 et y2.

L'axe des x reste systématiquement à 10 car nous dessinons une ligne vers le bas plutôt que de gauche à droite. Nous allons stocker deux nombres dans les données: la quantité que nous voulons que notre espacement soit, qui sera num1, et le montant que nous voulons que notre marge soit, qui sera num2.

data() {
  return {
    num1: 32,
    num2: 15,
    // ...
  }
}

L'axe y commence par num2, qui est soustraite de la fin, ainsi que la marge. le tasks.length est multiplié par l'espacement, qui est num1.

Maintenant, nous aurons besoin des cercles qui se trouvent sur la ligne. Chaque cercle est un indicateur pour savoir si une tâche est terminée ou non. Nous aurons besoin d'un cercle pour chaque tâche, nous utiliserons donc v-for avec un unique key, qui est l'index (et peut être utilisé en toute sécurité ici car ils ne seront jamais réorganisés). Nous allons connecter le click directive avec notre méthode et transmettez également l'index en tant que paramètre.

Les cercles en SVG sont constitués de trois attributs. Le milieu du cercle est tracé à cx et cy, puis nous dessinons un rayon avec r. Comme la ligne, cx commence à 10. Le rayon est de 4 car c'est ce qui est lisible à cette échelle. cy sera espacé comme la ligne: index multiplié par l'espacement (num1), plus la marge (num2).

Enfin, nous allons utiliser un ternaire pour définir le fill. Si la tâche est terminée, elle sera remplie de currentColor. Sinon, il sera rempli de white (ou quel que soit le fond). Cela pourrait être rempli d'un accessoire qui passe en arrière-plan, par exemple, là où vous avez des cernes et des cernes.

Enfin, nous utilisons la grille CSS pour aligner un div avec les noms des tâches. Ceci est présenté de la même manière, lorsque nous parcourons les tâches en boucle, et nous sommes également liés à ce même événement de clic pour basculer l'état terminé.

le Version React

Voici où nous nous sommes retrouvés avec la version React. Nous travaillons à l'open sourcing afin que vous puissiez voir le code complet et son historique. Voici quelques modifications:

  • Nous utilisons des modules CSS plutôt que les SCF dans Vue
  • Nous importons le lien Next.js, de sorte qu'au lieu de basculer vers l'état "terminé", nous dirigeons un utilisateur vers une page dynamique dans Next.js
  • Les tâches que nous utilisons sont en fait des étapes du cours – ou «Mission» comme nous les appelons – qui sont transmises ici plutôt que détenues par le composant.

La plupart des autres fonctionnalités sont les mêmes 🙂

import styles from './MissionTracker.module.css';
import React, { useState } from 'react';
import Link from 'next/link';

function MissionTracker({ currentMission, currentStage, stages }) {
 const (tasks, setTasks) = useState((...stages));
 const num1 = (32);
 const num2 = (15);

 const updateDoneTasks = (index) => () => {
   let tasksCopy = (...tasks);
   tasksCopy(index).done = !tasksCopy(index).done;
   setTasks(tasksCopy);
 };

 const taskTextStyles = (task) => {
   const baseStyles = `${styles('tracker-select')} ${styles('task-label')}`;

   if (currentStage === task.slug.current) {
     return baseStyles + ` ${styles('is-current-task')}`;
   } else {
     return baseStyles;
   }
 };

 return (
   
{tasks.map((task, index) => (
{task.title}
))}
timeline element {tasks.map((task, index) => ( ))}
); } export default MissionTracker;

Version finale

Vous pouvez voir la version finale de travail ici:

Ce composant est suffisamment flexible pour accueillir des listes petites et grandes, plusieurs navigateurs et un dimensionnement réactif. Cela permet également à l'utilisateur de mieux comprendre où il en est dans sa progression dans le cours.

Mais ce n'est qu'un élément. Vous pouvez créer n’importe quel nombre d’éléments de l’interface utilisateur: boutons, commandes, indicateurs de progression, chargeurs… le ciel est la limite. Vous pouvez les styliser avec du CSS ou des styles en ligne, vous pouvez les mettre à jour en fonction des accessoires, du contexte, des données réactives, le ciel est la limite! J'espère que cela vous permettra de développer vous-même des éléments d'interface utilisateur plus attrayants pour le Web.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *