Maison >interface Web >js tutoriel >Construire une grille d'images dynamique avec Svelte : implémenter des transitions de cartes à retourner
La création d'interfaces utilisateur attrayantes nécessite souvent un équilibre délicat entre fonctionnalité et attrait visuel. Dans cet article, nous explorerons comment créer un composant de grille d'images dynamique à l'aide de Svelte qui non seulement gère efficacement l'état, mais fournit également des transitions fluides et accrocheuses lorsque les images entrent et sortent.
Imaginez une grille d'images qui se rafraîchit périodiquement, avec des cartes individuelles se retournant en douceur pour révéler de nouvelles images.
Cela crée un affichage attrayant, parfait pour présenter les membres de l'équipe, les catalogues de produits ou toute collection d'images plus grande que ce qui peut être affiché simultanément.
C'est ce que j'ai dû créer pour un widget de grille d'images présentant une liste de membres. Les images des membres proviennent d'une API et s'agrandissent avec le temps.
J'ai décidé de construire ça avec Svelte parce que, pourquoi pas ?!
Plus sérieusement, je voulais quelque chose qui serait compilé avec juste la quantité de code nécessaire et qui aurait une très petite empreinte sur le site Web.
Sur cette base, j'avais deux options :
De plus, je trouve le modèle svelte plus simple et plus intuitif donc étant donné le choix, surtout sur un petit projet comme celui-ci, c'est ce que je choisirai par défaut.
Comme vous le verrez un peu plus loin, svelte rend la gestion de nombreux changements d'état petits et complexes très simple par rapport à d'autres solutions (encore une fois, goût personnel).
Il y a généralement moins de façons de gâcher les choses.
Notre implémentation se compose de deux composants Svelte principaux :
Le cœur de notre widget réside dans sa gestion d'état. Nous devons suivre plusieurs informations :
let allImages: Image[]; // All available images let imagesToUse: Image[] = []; // Initial grid images let imagesInUse: Image[] = []; // Current grid state let remainingImages: Image[] = []; // Pool of unused images let imagesSwapMap = new Map<number, Image>(); // Tracks pending swaps
Vous vous demandez peut-être pourquoi nous maintenons imagesInUse séparément de imagesToUse. Cette séparation répond à plusieurs objectifs cruciaux :
Le processus d'échange d'images est une séquence soigneusement orchestrée qui garantit des transitions fluides tout en maintenant l'intégrité de la grille. Décomposons la fonction switchImages étape par étape :
let allImages: Image[]; // All available images let imagesToUse: Image[] = []; // Initial grid images let imagesInUse: Image[] = []; // Current grid state let remainingImages: Image[] = []; // Pool of unused images let imagesSwapMap = new Map<number, Image>(); // Tracks pending swaps
Tout d'abord, nous devons déterminer quelles images de notre pool restant seront utilisées pour l'échange :
const switchImages = () => { let newImagesSwapMap = new Map<number, Image>() let remainingImagesToUse let newRemainingImages: Image[]
Ce code gère deux scénarios :
Ensuite, nous sélectionnons au hasard les positions dans la grille où nous échangerons les images :
if (remainingImages.length <= NUMBER_OF_IMAGES_TO_SWITCH) { // If we have fewer remaining images than needed, use all of them remainingImagesToUse = remainingImages.slice(0); newRemainingImages = []; } else { // Take the last N images from the remaining pool remainingImagesToUse = remainingImages.slice(-NUMBER_OF_IMAGES_TO_SWITCH); // Keep the rest for future swaps newRemainingImages = remainingImages.slice(0, -NUMBER_OF_IMAGES_TO_SWITCH); }
Cela crée un tableau d'index aléatoires dans la taille de notre grille. Par exemple, si NUMBER_OF_IMAGES_TO_SWITCH vaut 1 et NUMBER_OF_IMAGES_TO_USE vaut 16, nous pourrions obtenir [7], indiquant que nous échangerons l'image à la position 7 dans la grille.
Avant d'effectuer tout échange, nous vérifions si la nouvelle image est déjà affichée :
indexesToSwap = Array(NUMBER_OF_IMAGES_TO_SWITCH) .fill(null) .map(() => Math.floor(Math.random() * NUMBER_OF_IMAGES_TO_USE));
Cette fonction évite qu'une même image apparaisse plusieurs fois dans notre grille.
Vient maintenant la logique d'échange de base :
const imageIsInUse = (image: Image) => { const inUse = imagesInUse.find((img: Image) => image.picture_url === img.picture_url); return inUse; };
Décomposons ce qui se passe dans chaque échange :
Après avoir effectué tous les échanges, nous mettons à jour notre état :
for (let i = 0; i < indexesToSwap.length; i++) { let index = indexesToSwap[i]; let imageToSwap = imagesInUse[index]; // Current image in the grid let imageToSwapWith = remainingImagesToUse.pop(); // New image to display if (imageToSwapWith && !imageIsInUse(imageToSwapWith)) { // Record the swap in our map newImagesSwapMap.set(index, imageToSwapWith); // Update the swap map to trigger component updates imagesSwapMap = newImagesSwapMap; // Update the grid state imagesInUse[index] = imageToSwapWith; // Add the old image back to the pool newRemainingImages.unshift(imageToSwap); } else { return; // Skip if the image is already in use } }
Les imagesSwapMap sont la clé pour déclencher des animations. Lors de sa mise à jour, les composants MemberImageCard concernés réagissent :
remainingImages = newRemainingImages; imagesInUse = imagesInUse;
Cette déclaration réactive dans MemberImageCard :
La beauté de ce système est qu'il maintient une expérience utilisateur fluide tout en garantissant :
Chaque composant MemberImageCard gère sa propre animation flip à l'aide de transformations et de transitions CSS. La magie opère grâce à une combinaison de suivi d'état et de CSS :
let allImages: Image[]; // All available images let imagesToUse: Image[] = []; // Initial grid images let imagesInUse: Image[] = []; // Current grid state let remainingImages: Image[] = []; // Pool of unused images let imagesSwapMap = new Map<number, Image>(); // Tracks pending swaps
const switchImages = () => { let newImagesSwapMap = new Map<number, Image>() let remainingImagesToUse let newRemainingImages: Image[]
Lorsqu'une image doit être échangée, nous :
Pour améliorer l'expérience utilisateur, nous avons mis en place un effet de chargement progressif :
if (remainingImages.length <= NUMBER_OF_IMAGES_TO_SWITCH) { // If we have fewer remaining images than needed, use all of them remainingImagesToUse = remainingImages.slice(0); newRemainingImages = []; } else { // Take the last N images from the remaining pool remainingImagesToUse = remainingImages.slice(-NUMBER_OF_IMAGES_TO_SWITCH); // Keep the rest for future swaps newRemainingImages = remainingImages.slice(0, -NUMBER_OF_IMAGES_TO_SWITCH); }
Les images commencent à être floues et s'estompent doucement une fois chargées, offrant ainsi une apparence et une sensation soignées.
Les échanges d'images réguliers sont planifiés à l'aide de la fonction de cycle de vie onMount de Svelte :
indexesToSwap = Array(NUMBER_OF_IMAGES_TO_SWITCH) .fill(null) .map(() => Math.floor(Math.random() * NUMBER_OF_IMAGES_TO_USE));
Cette implémentation met en valeur la puissance des capacités réactives de Svelte combinées aux transformations CSS modernes pour créer un composant d'interface utilisateur dynamique et attrayant.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!