Comment j'ai fait un curseur vraiment adaptatif (carrousel)

Bonjour, chers lecteurs et écrivains!


Aujourd'hui, je vais vous dire comment le projet m'a confronté à la tâche de fabriquer un curseur adaptatif et ce qui en est sorti


À propos de l'article et pour qui il est


J'écris cet article non pas tant parce que je veux que la communauté réponde à ce problème, mais aussi parce que la résolution des questions de l'article me semble fondamentale pour comprendre l'adaptabilité du curseur sur le web. Si quelqu'un a déjà écrit de tels composants, veuillez répondre et partager des expériences similaires


Un peu sur ce qui s'est passé et quels outils ont été utilisés


Dans une application React, vous devez réaliser un carrousel (ci-après j'utiliserai ce nom), dont les éléments se regardent harmonieusement sur l'écran de toute taille. Il existe plusieurs limitations:


  1. La largeur maximale de l'élément est de 150 px
  2. Outil utilisé - Carrousel React Owl
  3. La taille maximale du conteneur pour le carrousel est de 1190 px
  4. Il existe également des indicateurs de la propriété de remplissage pour différents écrans (affecte la largeur de la partie visible du conteneur) et la marge (entre les éléments d'au moins 5 pixels)
  5. Le carrousel doit aller en cycles
    Et d'autres conditions qui n'affectent pas le sujet de l'article

Digression sur la mécanique du carrousel


De nombreux carrousels (React Owl Carousel ne fait pas exception) utilisent la classe active spéciale pour montrer qui décrit les éléments actuellement affichés à l'écran.


Pour afficher une boucle infinie à l'écran, les premier et dernier éléments sont dupliqués (les mécanismes et les problèmes de ce doublage font l'objet d'un article séparé).


Les propriétés sont décrites par des objets spéciaux, nous nous intéresserons à l'objet réactif, qui est responsable de la réaffectation des propriétés.


Le reste des données sur la mécanique du travail sera clair au cours de la description de la solution.


Premiers problèmes


Au début, tout s'est bien passé - les éléments eux-mêmes ont été écrits et stylisés, les propriétés de base de l'ensemble du carrousel ont été énoncées. Des problèmes ont commencé lors de la définition de la propriété {loop: true}


Le carrousel ne boucle pas correctement


Lors du défilement à la fin de la liste, l'espace libre est resté dans le carrousel et pendant un certain temps, il l'a parcouru.


La raison en était la largeur maximale de l'élément, non cohérente avec leur nombre. Un exemple concret est la largeur du conteneur 1190 px, avec le nombre d'éléments défini sur 3.


En d'autres termes, le carrousel s'attend à ce que 3 éléments s'étendent jusqu'à 1190 pixels et ils ne peuvent pas dépasser 150 pixels.


Augmenter le nombre d'articles


Le problème prend un angle différent: s'il y a trop d'éléments par conteneur, leur largeur devient trop petite (et il y a du contenu à l'intérieur!) Si je définis la propriété min-width, alors sur certaines tailles d'écran les éléments rampent les uns sur les autres, ignorant la marge, ce qui viole les conditions .


Nous résumons les conditions d'adaptabilité


  1. Le nombre d'éléments sur l'écran doit être inférieur au rapport entre la taille de l'écran et
    largeur minimale de l'élément - sinon, même les éléments de la largeur minimale ne tiendront pas sur l'écran.
  2. Le rapport entre la taille de l'écran et le nombre estimé d'éléments ne doit pas dépasser la longueur maximale estimée, sinon il y a un problème avec le bouclage.
  3. Les conditions décrites ci-dessus doivent être remplies pour toute taille d'écran (de 330px à 1190px).

Nous résolvons le problème en tant que programmeurs


Si vous abordez le problème de manière séquentielle, il est évident que vous devez abandonner quelque chose, dans mon cas, c'était la largeur minimale de l'élément.


Quelle devrait être la largeur minimale de l'élément pour que pour tous les tamis à conteneurs les conditions d'adaptabilité soient remplies?


//       const getBackTrace = (minScreen = 300, maxElementWidth = 150) => { let backTrace = {} for (let minElementWidth = maxElementWidth; minElementWidth > 0; minElementWidth--){ //            //     backTrace for(let screen = minScreen; screen <= 1100; screen++){ let elementCount = screen / minElementWidth | 0 if((screen / elementCount) > maxElementWidth){ backTrace[minElementWidth] = screen break } } } for(let key in backTrace){ //        ,      if (backTrace[key - 1] == undefined){ backTrace.result = key - 1 return backTrace } } } // getBackTrace(300, 150).result = 100 

Le résultat en 100px ne me convenait pas, car il ne me permet pas d'ajuster tout le contenu de l'élément. Par conséquent, nous continuons la recherche jusqu'à ce que nous trouvions la bonne valeur et recherchons quoi d'autre à sacrifier.


Rappelez-vous le sous-titre? Pour rechercher, écrivez une fonction


 const getMinScreen = (minWidth = 300, maxWidth = 767, maxElementWidth = 150) => { let research = [] //  ,          // getBackTrace,       for(let min = minWidth; min < maxWidth; min++){ let { result } = getBackTrace(min, maxElementWidth) research.push({result, min}) } //          "  "  return research .reduce((acc, curr, idx, arr) => { let obj = {} let {min, result} = curr obj[min] = result if(idx == 0) return obj if(arr[idx-1].result == result){ return {...acc} } else { return {...acc, ...obj} } }, {}) } /* Returned object {300: 100, 303: 101, 306: 102, 309: 103, 312: 104, 315: 105, 318: 106, 321: 107, 324: 108, 327: 109, 330: 110, 333: 111, 336: 112, 452: 113, 456: 114, 460: 115, 464: 116, 468: 117, 472: 118, 476: 119, 480: 120}   480    */ 

En considérant l'objet obtenu, vous pouvez voir un grand saut dans la transition de 336px à 452px.
J'ai pris la ferme décision de limiter l'adaptabilité à 36 pixels.


Nous décrivons l'objet adaptatif


Il semblerait que le problème soit résolu, mais une telle solution ne fait que prouver que le respect des conditions est possible pour les écrans à partir de 336 pixels, mais ne décrit pas la méthode. Mais il y a différentes conditions qui me limitent dans la production d'un objet aux propriétés d'adaptabilité
Après avoir accepté pour moi-même que la largeur minimale d'un élément sans pertes peut être de 107 px, en variant la valeur de la marge, je suis arrivé aux indicateurs suivants:


Écranmargelargeur minimale
336+5107
468+10107
763+15112

Il ne reste plus qu'à collecter les données reçues dans un tas et implémenter l'objet adaptatif:


 getResponsiveOwlItems = () => { let responsive = {}; responsive[0] = {items: 2, nav: false} // 112 = 107 (minimal div) + 5 (margins) let itemMinWidthReference = 112; const getOneWidth = deviceWidth => deviceWidth / itemMinWidthReference | 0 // 1190 - container width for(let i = itemMinWidthReference * 3 + 20; i <= 1190; i += itemMinWidthReference){ // .container padding > 768 90px + padding 90(.container) // .container padding < 768 40px + padding -40(.container) // +20px stagePadding let padding = i > 767 ? 200 : 20 if(i > (468 + padding)) { itemMinWidthReference = 117 } if(i > (767 + padding)) { itemMinWidthReference = 127 } let items = getOneWidth(i - padding) let nav = i > 700 ? true : false let margin = 5; if (i > 468){ margin = 10 } if (i > 767){ margin = 15 } responsive[i.toString()] = {items, nav, margin} //      itemMinWidthReference i = i - (i % itemMinWidthReference) + 1 } return responsive; } 

Le jour de la publication, tout semble logique et je n'ai pas pu reproduire l'erreur dans le carrousel - tout fonctionne probablement comme prévu.


Merci de votre attention, en attendant vos commentaires et commentaires!

Source: https://habr.com/ru/post/fr461525/


All Articles