Construire un Scroller Image jQuery

Dans ce didacticiel, nous allons créer un scroller d’images, en utilisant les excellentes fonctions d’animation de jQuery et en nous amusant généralement avec du code. Les défileurs d'images ne sont bien sûr pas nouveaux. des versions d’elles sortent tout le temps. Beaucoup d'entre eux sont toutefois initiés par l'utilisateur. ce qui signifie que pour que le contenu affiché change, le visiteur doit cliquer sur un bouton ou effectuer une autre action. Cette barre de défilement sera différente en ce sens qu'elle sera complètement autonome et commencera à défiler une fois la page chargée..


Le widget fini sera complètement cross-browser et fonctionnera comme prévu dans les dernières versions de tous les navigateurs les plus courants. Nous allons également intégrer certaines interactions en ajoutant des contrôles permettant au visiteur de changer le sens de l'animation. Nous allons travailler avec seulement jQuery et un peu de HTML et CSS dans ce tutoriel et devrions être en mesure d'exécuter les exemples sans configuration complète du serveur Web..


Commencer

Créons d'abord la page HTML sous-jacente; Dans une nouvelle page de votre éditeur de texte, ajoutez le code suivant:

      imageScroller Image Carousel   
Pomme Firefox jQuery Gazouillement jQuery UI

Enregistrer ceci sous imageScroller.html dans un nouveau dossier. Nous établissons un lien vers une feuille de style personnalisée dans l'en-tête de la page, que nous coderons dans un instant, et nous incluons un lien vers la version hébergée de la dernière version de jQuery au bas de la page. Le chargement de scripts à la fin du corps est une technique reconnue pour améliorer les performances de votre page et doit donc être pratiqué dans la mesure du possible..

Notre widget est constitué d'une série de conteneurs imbriqués et d'un ensemble d'images encapsulées dans des liens. Les images placées dans les conteneurs sont codées en dur dans la page pour des raisons d'accessibilité. Nous ne récupérerons pas les images de manière dynamique. toutes les images placées dans le widget défileront automatiquement (à condition qu'elles soient entourées d'un lien avec le nom de la classe appropriée).

Le conteneur le plus externe sera utilisé principalement à des fins de positionnement et d'affichage, tandis que le conteneur suivant est utilisé pour décorer le widget avec une image d'arrière-plan. Le conteneur externe est également nécessaire pour ajouter les contrôles à afin qu’ils apparaissent correctement au-dessus du contenu dans IE..

Le conteneur le plus à l'intérieur est l'élément qui sera utilisé pour visualiser les images. Cet élément est attribué à la classe js-disabled qui sera utilisée uniquement pour les visiteurs dont JavaScript est désactivé. Nous allons utiliser cette classe pour réduire chacune des images avec CSS afin qu'elles soient toutes visibles.

Les images ont toutes une taille uniforme et les contenants seront dimensionnés pour les accueillir parfaitement. La taille de l'image est également utilisée dans le script que nous allons ajouter. Je soulignerai précisément où ces références se trouvent, mais vous devez savoir que si vous souhaitez utiliser des images de taille différente, le script et la taille des conteneurs doivent être ajustés en conséquence..


Styliser le widget

Après le lien vers jQuery, nous avons un élément de script personnalisé avec le jQuery document.ready raccourci, en attendant que nous ajoutions le code qui donnera vie au widget. Avant de faire cela, ajoutons simplement le CSS rapidement. Dans un autre nouveau fichier de votre éditeur de texte, ajoutez les sélecteurs et les règles de style suivants:

 / * js-disabled class - définit la taille des images pour qu'elles puissent toutes s'intégrer dans le visualiseur * / .js-disabled img width: 100px; hauteur: 100px; bloc de visualisation; float: gauche; marge: 30px 0 0;  #outerContainer width: 542px; hauteur: 202px; marge: auto; position: relative;  #imageScroller width: 542px; hauteur: 202px; position: relative; fond: # 000000 url (images / imageScrollerBG.png) no-repeat;  #viewer width: 522px; hauteur: 182px; débordement caché; marge: auto; position: relative; en haut: 10 px;  #imageScroller a: actif, #imageScroller a: visité color: # 000000;  #imageScroller a img border: 0;  #controls width: 534px; hauteur: 47px; fond: url (images / controlsBG.png) no-repeat; position: absolue; en haut: 4 px; à gauche: 4px; z-index: 10;  #controls a width: 37px; hauteur: 35px; position: absolue; en haut: 3px;  #controls a: actif, #controls a: visité color: # 0d0d0d;  #title color: #ffffff; famille de polices: arial; taille de police: 100%; poids de police: gras; largeur: 100%; text-align: center; marge supérieure: 10 px;  # rtl background: url (images / rtl.png) no-repeat; à gauche: 100px;  #rtl: hover background: url (images / rtl_over.png) no-repeat; à gauche: 99px;  #ltr background: url (images / ltr.png) no-repeat; à droite: 100px;  #ltr: hover background: url (images / ltr_over.png) no-repeat; 

Si JavaScript est désactivé et que la page est en cours de chargement, toutes les images seront visibles.

Enregistrer ceci sous imageScroller.css dans le même dossier que la page Web. Nous avons d’abord le sélecteur de classe qui cible notre js-disabled classe; Avec ces règles, nous dimensionnons simplement les images de manière à ce qu'elles soient suffisamment petites pour s'empiler les unes sur les autres sur toute la largeur du widget. Si JavaScript est désactivé et que la page est en cours de chargement, toutes les images seront visibles - un repli très rapide et facile, mais qui ne sera pas nécessairement à l'abri de toute erreur et ne sera certainement pas une amélioration progressive complète. Les valeurs spécifiées pour la largeur et la hauteur devront varier en fonction du nombre d'images dans la visionneuse..

Nous avons ensuite les sélecteurs et les règles qui modèlent le widget et le font fonctionner correctement. La plupart du code utilisé ici est uniquement destiné à l'affichage, aux images d'arrière-plan, aux couleurs, etc. Une règle importante, sur laquelle repose l'implémentation pour fonctionner correctement, est le paramètre de débordement: masqué sur le conteneur du visualiseur interne. Ceci cachera les images qui doivent encore être montrées et les images qui ont déjà passé par le spectateur. A ce stade, lorsque nous courons la page, nous devrions voir quelque chose comme ceci:

Certains des CSS que nous allons définir dans JavaScript dans quelques instants et certains des éléments que nous ciblons dans le CSS n'existent pas encore, mais c'est tout ce qui doit être inséré dans le fichier CSS..


Donner vie au widget

Dans la dernière étape de ce didacticiel, nous ajouterons le code JavaScript au style jQuery qui assurera le fonctionnement du widget et créera le comportement souhaité. Dans la fonction anonyme anonyme au bas de la page HTML, ajoutez le code suivant:

 // supprime la classe js-disabled $ ("# visionneuse"). removeClass ("js-disabled"); // crée un nouveau conteneur pour les images $ ("
") .attr (" id "," conteneur "). css (position:" absolu "). width ($ (". wrapper "). length * 170) .height (170) .appendTo (" div # viewer "); // ajoute des images au conteneur $ (". wrapper "). each (function () $ (this) .appendTo (" div # container ");); // détermine la durée de l'animation en fonction de nombre d'images (1 seconde pour chaque image) var duration = $ (". wrapper"). length * 1000; // enregistre la vitesse pour une vitesse var ultérieure = (parseInt ($ ("div # conteneur"). width ()) + parseInt ($ ("div # viewer"). width ())) / duration; // définir la direction var direction = "rtl"; // définir la position initiale et la classe en fonction de la direction (direction == "rtl")? $ ("div # container"). css ("left", $ ("div # viewer"). width ()). addClass ("rtl"): $ ("div # container"). css ("left" , 0 - $ ("div # conteneur"). Width ()). AddClass ("ltr");

Tout d'abord, nous supprimons la classe js-disabled du conteneur Viewer. Ensuite, nous créons un nouveau conteneur pour contenir toutes les images trouvées dans le widget. La raison principale en est qu’au lieu d’animer chaque image individuellement, ce qui entraîne potentiellement un grand nombre d’animations simultanées, il ne reste plus qu’à animer un élément - le conteneur que nous créons maintenant..

La largeur du nouveau conteneur est définie sur le nombre d'images multiplié par la largeur de chaque image, qui dans cet exemple est de 170 pixels. C’est l’un des éléments de code que j’ai dit plus tôt que je voudrais mentionner, et c’est quelque chose qui devra être changé si nous décidons d’utiliser des images de taille différente. La hauteur du conteneur est également spécifiquement définie sur la hauteur de chaque image..

Il est utile ultérieurement dans le script de connaître certaines informations sur la nature de l'animation, telles que sa vitesse, sa durée et la direction du déplacement. Nous allons ensuite définir une série de variables pour stocker ces informations. La durée correspondra exactement à une seconde par image et est basée à nouveau sur le nombre d'images trouvées dans le widget..

La vitesse est facile à calculer, étant bien entendu la distance parcourue divisée par la durée du trajet. Pour référence, dans cet exemple, la vitesse exacte de l'animation sera de 0,274 pixels par milliseconde. La dernière variable, direction, est une simple chaîne indiquant que l’animation se déroulera de droite à gauche, bien que nous puissions facilement le remplacer par ltr si nous le souhaitions..

Enfin, nous définissons la position de départ du nouveau conteneur; l'animation étant actuellement définie sur rtl, nous devons positionner le nouveau conteneur d'image de sorte que son bord gauche soit défini sur le bord droit du visualiseur. Si nous définissons toutefois l'animation sur ltr, le bord droit de l'élément sera aligné sur le bord gauche du conteneur. Nous déterminons la direction en utilisant la condition ternaire JavaScript. En plus de sa position, nous donnons également au nouveau conteneur un nom de classe correspondant à sa direction, que nous pouvons tester à différents moments du script..

Ensuite, nous devrons définir une nouvelle fonction pour lancer et perpétuer l’animation. L'exécution normale du script nécessite plusieurs moments différents pour l'animation. Par conséquent, intégrer cette fonctionnalité dans une fonction que nous pouvons appeler lorsque nous en avons besoin contribue à réduire la quantité de code. Ajoutez le code suivant:

 // fonction animateur var animator = fonction (el, time, dir) // direction à suivre si (dir == "rtl") // ajoute la classe de direction el.removeClass ("ltr"). addClass ("rtl "); // animer el el.animate (left: "-" + el.width () + "px", time, "linear", function () // réinitialiser la position du conteneur $ (this) .css ( left: $ ("div # imageScroller"). width (), right: ""); // redémarre l'animateur d'animation ($ (this), duration, "rtl"); // masque les contrôles visibles ($ (" div # controls "). length> 0)? $ (" div # controls "). slideUp (" slow "). remove (): null;);  else // ajouter une classe de direction el.removeClass ("rtl"). addClass ("ltr"); // animer el el.animate (left: $ ("div # viewer"). width () + "px", time, "linear", function () // réinitialise la position du conteneur $ (this). css (left: 0 - $ ("div # conteneur"). width ()); // redémarre l'animateur d'animation ($ (this), durée, "ltr"); // masque les contrôles s'ils sont visibles ($ (" div # controls "). length> 0)? $ (" div # controls "). slideUp (" slow "). remove (): null;); 

La fonction animateur accepte trois arguments; l'élément à animer, la durée pendant laquelle l'animation doit s'exécuter et la direction dans laquelle l'élément doit être animé. La fonction est divisée en deux blocs distincts, l’un pour l’animation RTL et l’autre pour LTR..

Dans chaque bloc de la condition, nous mettons à jour le nom de classe du conteneur d'image pour refléter la direction actuelle au cas où la direction aurait changé (il s'agit d'une des interactions initiées par le visiteur)..

Nous définissons ensuite l’animation en déplaçant le conteneur d’images plus pour ltr ou moins pour rtl la largeur du conteneur d’images, ce qui lui donne l’impression de glisser à travers le spectateur. Malheureusement, nous ne pouvons pas utiliser les animations intégrées lente, normale ou rapide, car même le paramètre lent réduit l'animation à une durée totale d'exécution de seulement 600 millisecondes, ce qui est beaucoup trop rapide, même pour le petit nombre d'images que nous utilisons. dans cet exemple.

Nous spécifions la chaîne linéaire comme troisième argument de la méthode animate, qui est la fonction d'accélération à utiliser, et définit l'animation pour qu'elle se déroule à une vitesse uniforme du début à la fin. si nous ne définissions pas cela, l'animation accélérerait et ralentirait sensiblement au début et à la fin de l'animation, respectivement.

Enfin, nous ajoutons une fonction de rappel anonyme qui sera exécutée dès la fin de l’animation; au sein de cette fonction de rappel, nous ramenons le conteneur d'images à sa position de départ, appelons de manière récursive la fonction d'animateur en transmettant à nouveau les paramètres corrects en fonction de la branche du conditionnel en cours d'exécution et masquons le panneau de configuration s'il est visible. Nous n'avons pas encore ajouté le code qui créera le panneau de configuration, mais nous avons encore besoin d'ajouter ce code ici lorsque nous aurons.

Pour lancer l'animation lorsque la page est chargée, nous devons maintenant appeler la fonction que nous venons de définir. ajoutez l'appel de fonction suivant:

 // démarrer anim animator ($ ("div # conteneur"), durée, direction);

Nous appelons simplement la fonction transmettant l'élément à animer et les variables que nous avons définies dans la première section de code. Si nous exécutons la page maintenant, nous devrions constater que l'animation commence dès que la page s'est chargée et continue indéfiniment, comme indiqué (en quelque sorte) dans la capture d'écran suivante:


Ajouter de l'interaction

Nous en sommes maintenant au stade où nous disposons des fonctionnalités de base du widget et pouvons commencer à ajouter une interactivité supplémentaire qui le rendra attrayant. Après l'appel de la fonction d'animation, ajoutez le code suivant:

 // pause sur mouseover $ ("a.wrapper"). live ("mouseover", function () // stop anim $ ("div # conteneur"). stop (true); // affiche les contrôles ($ (" div # controls "). length == 0)? $ ("

Comme le commentaire l'indique, ce gestionnaire d'événements arrête l'animation lorsque le visiteur survole le pointeur sur l'une des images du widget..

Nous utilisons la méthode live jQuery (nouvelle version 1.3!) Pour associer le gestionnaire aux éléments et spécifier une fonction anonyme à exécuter lorsque l'événement se produit..

Dans cette fonction, nous arrêtons d'abord l'animation à l'aide de la méthode jQuery stop, en transmettant une valeur booléenne vraie en tant qu'argument. Cet argument annulera la file d'attente d'animation si elle existe. cela ne devrait pas être fait, car il ne devrait y avoir qu'une seule animation à la fois, mais il est utile d'utiliser cet argument au cas où.

Nous vérifions si le panneau de contrôle existe déjà et, à condition que nous ne créions pas un nouvel élément div, lui attribuons un identifiant afin qu'il prenne nos règles de style et les ajoute au conteneur externe. Nous utilisons ensuite la méthode css de jQuery pour définir l'opacité en mode multi-navigateurs afin d'éviter de devoir cibler différents navigateurs avec notre CSS, et de faire glisser les contrôles en place..

Nous créons également des liens et les ajoutons au panneau de configuration; Ces liens serviront de boutons permettant au visiteur de changer le sens de déplacement des images. Nous allons ajouter des gestionnaires pour ces boutons dans un instant. Enfin, nous obtenons le contenu de l'attribut title du lien wrapper qui a déclenché l'événement mouseover et créons un nouvel élément de paragraphe dont le texte interne est défini sur le titre. Nous nous appuyons beaucoup sur le raccourci conditionnel ternaire JavaScript dans cette section de code car il fournit un excellent mécanisme pour créer et ajouter des éléments uniquement s'ils n'existent pas déjà..

Vous avez peut-être aussi remarqué que nous avons défini une variable pour contenir le contenu de l'attribut title du déclencheur actuel. Vous vous demandez peut-être pourquoi nous n'utilisons pas le code suivant à la place:

 // ajouter p si n'existe pas, le mettre à jour s'il existe ($ ("p # title"). length == 0)? $ ("

") .attr (" id "," title "). text ($ (this) .attr (" title ")). appendTo (" div # controls "): $ (" p # title "). text (title )

La raison en est qu'il n'y a aucune ambiguïté quant à ce que $ (this) désigne. L'utilisation du code ci-dessus fonctionne, mais elle génère des erreurs qui, bien que non fatales, ne sont toujours pas rassurantes pour les utilisateurs potentiels du widget. L'utilisation de la variable garantit simplement que ces erreurs sont évitées. Le panneau de configuration, lorsqu'il est visible, apparaît comme dans la capture d'écran suivante:

Après le survol de la souris, l'animation sera arrêtée. nous pouvons le redémarrer facilement en utilisant un gestionnaire d'événement mouseout, que nous devrions ajouter ensuite:

 // redémarre sur mouseout $ ("a.wrapper"). live ("mouseout", fonction (e) // masque les contrôles s'ils ne survolent pas (e.relatedTarget == null)? null: (e.relatedTarget. id! = "controls")? $ ("div # controls"). slideUp ("slow"). remove (): null; // calcule la distance totale parcourue var totalDistance = parseInt ($ ("div # container") .width ()) + parseInt ($ ("div # viewer"). width ()); // calcule la distance restante pour parcourir var distanceLeft = ($ ("div # conteneur"). hasClass ("ltr")) ? totalDistance - (parseInt ($ ("div # conteneur"). css ("à gauche")) + parseInt ($ ("div # conteneur"). width ())): totalDistance - (parseInt ($ ("div # viewer "). width ()) - (parseInt ($ (" div # conteneur "). css (" gauche ")))); // la nouvelle durée correspond à la distance gauche / vitesse) var newDuration = distanceLeft / speed; // redémarrer anim animator ($ ("div # conteneur"), newDuration, $ ("div # conteneur"). attr ("classe")); );

Encore une fois, nous utilisons la méthode live de jQuery, mais cette fois-ci, nous passons également l’objet événement raw dans notre fonction de rappel anonyme. Nous utilisons immédiatement cet objet pour voir si le pointeur est passé sur le panneau de commande. Si ce n'est pas le cas, nous masquons les contrôles, mais si c'est le cas, nous ne faisons rien et procédons au redémarrage de l'animation. Remarquez comment nous utilisons un ternaire imbriqué équivalent à un conditionnel if else.

L'objectif principal de la fonction anonyme est de redémarrer l'animation, mais avant de pouvoir le faire, nous devons déterminer la durée de l'animation. nous ne pouvons pas coder la valeur en dur car le conteneur d’images aura été déplacé. La durée initiale a été définie à 1 seconde pour chaque image, dans cet exemple 5 secondes. S'il ne reste qu'une seule image visible dans la visionneuse et que nous réglons à nouveau l'animation à 5 secondes, l'animation se déroulera nettement plus lentement..

Nous déterminons d’abord la distance totale parcourue par le conteneur d’images dans une animation complète. Nous déterminons ensuite combien de kilomètres il reste à parcourir. Nous aurons besoin de faire un calcul différent selon que l'animation se passe de gauche à droite ou inversement, nous utilisons donc à nouveau le conditionnel ternaire.

Si l'animation se déroule de gauche à droite, la distance restant à parcourir est l'attribut de style gauche du conteneur d'images (obtenu à l'aide de la méthode css jQuery) ajouté à la largeur du conteneur d'images, soustrait de la distance totale. Si le conteneur d'image se déplace de droite à gauche, la distance à parcourir est égale à la largeur du conteneur moins l'attribut de style gauche, soustrait de la distance totale. Les méthodes width et css jQuery retournent des valeurs de chaîne. Nous utilisons donc la fonction parseInt de JavaScript pour les convertir en valeurs numériques..

La nouvelle durée de l'animation est ensuite calculée en divisant la distance qu'il reste à parcourir par la vitesse que nous avons définie dès le début du code. Une fois que nous avons ce chiffre, nous pouvons appeler la fonction d’animation en passant à nouveau les paramètres requis, ce qui permet de relancer l’animation à partir de son point d’arrêt, dans le même sens.


Changer de direction

Pour la dernière partie de notre script, nous pouvons ajouter les gestionnaires pour les liens dans le panneau de contrôle utilisés pour changer le sens de l'animation. Juste après le code que nous venons d’ajouter, entrez le code suivant:

 // gestionnaire pour le bouton ltr $ ("# ltr"). live ("clic", function () // stop anim $ ("conteneur div #"). stop (true); // noms de classe d'échange $ (" div # conteneur "). removeClass (" rtl "). addClass (" ltr "); // calcule la distance totale parcourue var totalDistance = parseInt ($ (" div # conteneur "). width ()) + parseInt ($ ( "div # viewer"). width ()) // // calcule la distance restante var distanceLeft = totalDistance - (parseInt ($ ("div # conteneur"). css ("à gauche")) + parseInt ($ ("div # conteneur "). width ())); // nouvelle durée est distance gauche / vitesse) var newDuration = distanceLeft / speed; // redémarrer anim animator ($ ("div # conteneur"), newDuration, "ltr"); );

Cette fonction, déclenchée par un clic sur le bouton gauche à droite, est relativement simple et contient un code très similaire à celui que nous avons déjà utilisé. nous arrêtons d'abord l'animation en cours (elle reprendra lorsque le visiteur déplacera le pointeur sur le panneau de commande), puis nous échangerons le nom de la classe pour qu'il corresponde à la nouvelle direction du voyage. Nous travaillons ensuite sur la nouvelle durée de l’animation de la même manière que nous l’avions déjà fait, avant d’appeler à nouveau notre fonction d’animation. Ceci est juste le gestionnaire pour le bouton ltr; le gestionnaire pour le bouton rtl est presque identique, mais utilise le calcul correct pour le sens de déplacement opposé:

 // gestionnaire pour le bouton rtl $ ("# rtl"). live ("clic", function () // stop anim $ ("conteneur div #"). stop (true) // // noms de classe d'échange $ (" div # conteneur "). removeClass (" ltr "). addClass (" rtl "); // calcule la distance totale parcourue var totalDistance = parseInt ($ (" div # conteneur "). width ()) + parseInt ($ ( "div # viewer"). width ()) // // calcule la distance restante var distanceLeft = totalDistance - (parseInt ($ ("div # viewer"). width ()) - (parseInt ($ ("div # container" ) .css ("left"))))); // nouvelle durée est distance gauche / vitesse) var newDuration = distanceLeft / speed; // redémarrer anim animator ($ ("div # conteneur"), newDuration, "rtl"); );

C’est maintenant tout le code que nous devons écrire. Si vous exécutez la page dans un navigateur, vous constaterez que le widget fonctionne comme prévu..


Résumé

Dans ce didacticiel, nous avons créé un widget amusant et interactif pour afficher une série d’images. Il pourrait être utilisé pour afficher les logos des fabricants des produits que vous vendez, les logos des logiciels que vous recommandez ou tout ce que vous aimez. Nous nous sommes principalement concentrés sur les aspects d'animation et d'interaction du widget, mais nous avons également envisagé des solutions telles que la fourniture d'une solution de secours de base en cas de désactivation de JavaScript dans le navigateur..