Pleins feux sur Stickie sous contrainte avec jQuery

Toutes les deux semaines, nous examinerons de manière ultra ciblée un effet intéressant et utile, un plugin, un hack, une bibliothèque ou même une technologie astucieuse. Nous tenterons ensuite de déconstruire le code ou de créer un petit projet amusant avec celui-ci..

Aujourd'hui, nous allons jeter un coup d'oeil à un plugin qui implémente un très bel effet - c'est assez difficile à expliquer en une phrase, vous pouvez donc aussi cliquer sur le bouton Continuer pour commencer après le saut..


Un mot de l'auteur

En tant que développeurs Web, nous avons accès à une quantité stupéfiante de code prédéfini, qu’il s’agisse d’un petit extrait de code ou d’un framework à part entière. À moins que vous ne fassiez quelque chose d'incroyablement précis, les chances sont, il y a déjà quelque chose de pré-construit pour que vous puissiez tirer parti. Malheureusement, beaucoup de ces offres stellaires languissent dans l'anonymat, spécialement à la foule non-hardcore.

Cette série cherche à rectifier ce problème en introduisant du code utile, extrêmement bien écrit - qu’il s’agisse d’un plugin, d’un effet ou d’une technologie pour le lecteur. De plus, s'il est suffisamment petit, nous tenterons de déconstruire le code et de comprendre comment il le fait vaudou. S'il est beaucoup plus volumineux, nous allons essayer de créer un mini-projet avec celui-ci pour apprendre les ficelles du métier et, espérons-le, comprendre comment en faire usage dans le monde réel..


Présentation de stickyFloat

Voici quelques infos rapides:

  • Type: Brancher
  • La technologie: JavaScript [Construit sur la bibliothèque jQuery]
  • Une fonction: Contenu flottant uniquement dans les limites des limites de son parent
  • Plugin homepage: Ici

Le problème

Dans de nombreux cas, le contenu doit être flottant lorsque vous faites défiler, mais seulement dans son parent.

Le contenu flottant lorsqu'un utilisateur fait défiler le reste de la page est un jeu d'enfant. Aucun JavaScript n'est nécessaire - vous pouvez le faire avec tout simplement le vieux CSS. Slap a position: fixe déclaration sur it and boom !, vous avez un conteneur qui est fixé à un emplacement spécifique dans la page - il flotte dans la page pour être plus familier.

Mais regardons les choses en face, cela ne fonctionne pas avec toutes les mises en page. Vous pouvez planifier un peu à l’avance et le positionner sur la page de manière à ce qu’il n’interfère jamais avec des éléments importants, mais il ne serait ni complètement infaillible ni réutilisable ailleurs sans modifications importantes.

Dans ces cas, le contenu doit être flottant lorsque vous faites défiler, mais seulement dans son parent.. Si vous vous demandez, oui, cette fonctionnalité est une variante de celle qu'Andrew vous a montrée dans le tutoriel de la semaine dernière. C'est ainsi que j'ai appris à connaître ce plugin..

Comme vous le constaterez dans le développement Web, un peu comme le calcul multivarié, il existe souvent un certain nombre de solutions à un problème donné. Regardons l'une de ces solutions alternatives.


Déconstruire la logique

La logique générale ou le flux de travail de la fiche est en fait assez simple. Laisse moi te montrer. Gardez à l'esprit que je vais faire référence à l'élément qui doit être flotté comme gluant à partir de maintenant.

Mais avant de commencer, voici une rapide maquette montrant la hiérarchie:

Toute la logique du plugin peut être réduite à:

  • Calculer la position actuelle de l'élément collant parent, par rapport au document. Marqué comme 1 dans l'image.
  • Obtenir la taille du parent aussi - Donc, nous saurons quand arrêter de flotter lorsque nous aurons dépassé le parent. Marqué comme 2.
  • Calculer la distance parcourue par la page - Pour savoir si nous regardons le parent - pour voir si nous sommes dans la fourchette. Dans l'image ci-dessus, la ligne horizontale marque le haut hypothétique de la fenêtre actuelle. Dans ce cas, cette valeur sera la distance entre les points marqués 3.
  • En utilisant les deux valeurs que nous avons calculées ci-dessus, nous pouvons très rapidement déterminer si le sticky doit être repositionné correctement.

Si vous êtes confus, ne le soyez pas. Par exemple, regardons quelques exemples de numéros:

  • Le parent du sticky est présent 10px du haut de la page.
  • Le parent est 100px haute.
  • La page a été défilée 50px dans un scénario et 150px dans l'autre.

Donc, sur la base des informations ci-dessus, vous pouvez en déduire que

Dans le premier scénario - le collant doit être remis à flot de manière appropriée. Pourquoi? La page a été défilée 10px du haut - 10 vient de la page elle-même tandis que le reste vient du parent de l'adhésif. Ainsi, le parent est visible dans la fenêtre principale.

Dans le deuxième scénario - le collant peut être laissé seul. Sur 150px, 10 proviennent de la page, 100 de l'élément parent et le reste est occupé par le reste de l'élément de la page. Cela implique que l'utilisateur a défilé devant le parent et que nous n'avons rien à faire..

Si vous êtes encore flou à ce stade, ne vous inquiétez pas. Je vais expliquer un peu plus en parcourant la source.


Déconstruire la source

La source débarrassée des commentaires n’est qu’un petit peu plus de 30 lignes. Comme toujours, nous allons parcourir le code et expliquer ce que chaque ligne fait.

Voici la source, pour votre référence.

 $ .fn.stickyfloat = function (options, lockBottom) var $ obj = this; var parentPaddingTop = parseInt ($ obj.parent (). css ('padding-top')); var startOffset = $ obj.parent (). offset (). top; var opts = $ .extend (startOffset: startOffset, offsetY: parentPaddingTop, durée: 200, lockBottom: true, options); $ obj.css (position: 'absolute'); if (opts.lockBottom) var bottomPos = $ obj.parent (). height () - $ obj.height () + parentPaddingTop; si (bottomPos < 0 ) bottomPos = 0;  $(window).scroll(function ()  $obj.stop(); var pastStartOffset = $(document).scrollTop() > opts.startOffset; var objFartherThanTopPos = $ obj.offset (). top> startOffset; var objBiggerThanWindow = $ obj.outerHeight () < $(window).height(); if( (pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow ) var newpos = ($(document).scrollTop() -startOffset + opts.offsetY ); if ( newpos > bottomPos) newpos = bottomPos; if ($ (document) .scrollTop () < opts.startOffset ) newpos = parentPaddingTop; $obj.animate( top: newpos , opts.duration );  ); ;

Il est temps de voir ce qu'il fait réellement. Je vais supposer que vous avez une connaissance assez basique de JavaScript.

 $ .fn.stickyfloat = function (options, lockBottom) ;

Étape 1 - Le wrapper générique pour un plugin jQuery. Comme vous le savez probablement, options est un objet contenant des options variées pour configurer le comportement du plugin. lockbottom, Fait intéressant, spécifie si la fonctionnalité que nous voulons est activée ou non. Nous allons le laisser.

 var $ obj = this;

Étape 2 - Conservez une référence à l'élément passé. Dans ce contexte, ce pointe sur l’élément DOM qui correspond au sélecteur que vous avez transmis. Par exemple, si vous êtes passé à #menu, ce pointe vers l'élément avec cet ID.

 var parentPaddingTop = parseInt ($ obj.parent (). css ('padding-top'));

Étape 3 - Ceci est juste pour atténuer l'effet si l'élément parent a un grand rembourrage. Si oui, cela inclura le remplissage dans le calcul.

 var startOffset = $ obj.parent (). offset (). top;

Étape 4 - Nous calculons la position du parent par rapport au document en utilisant le décalage Méthode jQuery. Nous travaillons à travers le DOM en utilisant le parent méthode. nous $ obj puisque nous avons déjà mis en cache le sticky. Consultez la documentation de l'API jQuery si vous n'êtes pas familiarisé avec ces méthodes..

Dans ce cas, la distance par rapport au sommet est suffisante pour que nous acquérions cette valeur uniquement.

 var opts = $ .extend (startOffset: startOffset, offsetY: parentPaddingTop, durée: 200, lockBottom: true, options);

Étape 5 - Une jolie partie générique du processus de développement du plugin jQuery. Nous fusionnons essentiellement les options passées avec des préréglages pour obtenir un dernier ensemble d'options utilisé dans le code. Gardez à l'esprit que les paramètres passés ont toujours priorité sur les valeurs par défaut.

 $ obj.css (position: 'absolute');

Étape 6 - L'effet en question sera créé en manipulant l'élément Haut Valeur CSS, nous allons donc aller de l'avant et définir sa position sur absolue si elle n'a pas déjà été définie de cette façon.

 if (opts.lockBottom) var bottomPos = $ obj.parent (). height () - $ obj.height () + parentPaddingTop; si (bottomPos < 0 ) bottomPos = 0; 

Étape 7 - Comme indiqué ci-dessus, le lockbottom option spécifie si l'effet en question fonctionne ou non. Si activé, nous pouvons commencer à calculer. Ce que nous calculons, c’est le seuil au-delà duquel nous n’aurions pas besoin de repositionner le sticky.

Naturellement, vous pouvez simplement calculer la hauteur du parent, mais l'effet ne sera pas raffiné. Vous aurez besoin de prendre en compte la hauteur du collant lui-même le long de tout rembourrage sur le parent lui-même.

 $ (window) .scroll (function () // beaucoup de code)

Étape 8 - Nous accrochons notre code, dans une fonction anonyme, à la fenêtre faire défiler un événement. Certes, ce n'est pas la façon la plus efficace de procéder mais nous l'ignorerons pour l'instant..

 $ obj.stop ();

Étape 9 - Le premier ordre du mot est d'arrêter toutes les animations en cours sur l'élément collant. le Arrêtez la méthode prend soin de cela.

 var pastStartOffset = $ (document) .scrollTop ()> opts.startOffset; var objFartherThanTopPos = $ obj.offset (). top> startOffset; var objBiggerThanWindow = $ obj.outerHeight () < $(window).height();

Étape 10 - Ces trois variables contiennent des valeurs que nous utiliserons un peu plus tard.

  • pastStartOffset vérifie si nous avons fait défiler la limite supérieure de l'élément parent. Rappelez-vous, nous avons utilisé le décalage méthode pour trouver l'espace entre l'élément parent et le document. Nous obtenons à quel point vous avez fait défiler en utilisant le scrollTop méthode. C'est la distance entre le haut du document et le haut de la fenêtre courante..
  • objFartherThanTopPos vérifie si le post-it est dans sa position par défaut - en haut de son parent. Si nous avons fait défiler au-delà de la Haut du parent, nous ne voulons pas qu'il flotte à l'extérieur.
  • objBiggerThanWindow vérifie si la hauteur totale du collant est supérieure à la taille de la fenêtre. Si c'est le cas, il n'y a aucun intérêt à manipuler l'élément collant.
 if ((pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow) // Plus de code

Étape 11 - C'est ici que le plugin calcule s'il faut manipuler l'élément collant. Que fait la ligne ci-dessus:

  • Vérifier si l'utilisateur fait défiler exactement dans la plage de l'élément parent. Nous vérifions si l'utilisateur est en dessous de la limite supérieure du parent ou si le sticky est en haut.
  • Comme indiqué ci-dessus, nous ne procédons que si le sticky est plus petit que la taille de la fenêtre.

Nous procédons que si tous les deux de ces conditions sont remplies.

 var newpos = ($ (document) .scrollTop () -startOffset + opts.offsetY);

Étape 12 - Cette ligne définit une variable, newpos, qui spécifie la position dans laquelle l'élément collant doit être animé. Comme vous avez pu le constater, le calcul est assez basique si vous gardez à l’esprit l’image ci-dessus. Recherchez la distance parcourue, ajoutez-y le rembourrage supérieur du parent et soustrayez enfin la distance entre le document et le parent - le point de départ. Cela vous donne la distance, en pixels, entre le haut de l'élément parent et le point à l'intérieur, où le sticky doit être positionné.

 if (newpos> bottomPos) newpos = bottomPos;

Étape 13 - Si nous avons fait défiler au-delà de la limite inférieure de l'élément parent, nul besoin de manipuler davantage les choses. Verrouiller sa position là.

 if ($ (document) .scrollTop () < opts.startOffset ) newpos = parentPaddingTop;

Étape 14 - Si nous avons fait défiler au-dessus de la limite supérieure du parent, maintenez-le verrouillé afin d'éviter tout déplacement vers le haut..

 $ obj.animate (top: newpos, opts.duration);

Étape 15 - Terminé! Nous animons simplement l'élément collant en passant le nécessaire Haut valeur avec la durée de l'effet en utilisant le animer méthode jQuery.


Usage

Comme vous l'avez probablement probablement déduit à ce stade, l'utilisation ressemble à ceci:

 $ ('# menu'). stickyfloat (duration: 500);>

Au lieu d’expliquer l’exemple de mini-projet, comme la dernière fois, j’ai plutôt décidé de le construire et de vous donner le code..

Voici les parties pertinentes de la démo, le reste est passe-partout:

Le HTML

 
Menu collant
Je voulais écrire quelque chose d’incroyable, d’un esprit sans faille, ici. J'ai échoué. :(
Oui, je te suivrai partout tant que tu resteras avec mes parents
Vous vous attendiez à quelque chose d'intelligent ici, n'est-ce pas? Je sais que tu l'as fait! Fesser!

Le CSS

 .section padding: 10px; largeur: 900px; marge: 0 auto; couleur de fond: # f1f1f1; position: relative;  .section .content height: 800px; couleur de fond: #ddd; marge gauche: 250px; text-align: center; couleur: # 333; taille de police: 16px;  .section .menu position: absolute; à gauche: 10px; largeur: 240px; hauteur: 100px; arrière-plan: # 06C; text-align: center; couleur: #fff; taille de police: 14px; 

Le javascript

 $ ('# menu'). stickyfloat (duration: 400); $ ('# menu2'). stickyfloat (duration: 400);

Si vous parcourez les fichiers au fur et à mesure que vous lisez cet article, il devrait être assez explicite, mais n'hésitez pas à me poser des questions si une partie n'est pas claire.


Emballer

Et nous avons fini. Nous avons jeté un coup d'œil à un plugin incroyablement utile, parcouru le code source et avons finalement créé un mini-projet.

Des questions? De belles choses à dire? Des reproches? Hit la section des commentaires et laissez-moi un commentaire. Merci beaucoup pour la lecture!