[Mise à jour] jQuery – Effet smoothscroll au chargement de la page

Après une demande reçue par e-mail, je me suis dit que la fonctionnalité serait peut-être utile à d’autres que moi.
Lors de la rédaction de ce tutoriel : jQuery – Effet Smooth Scroll (défilement fluide), la complexité du contenu m’a fait retirer une extension intéressante à la dernière fonction/plugin proposée.

Avant propos

C’est toujours dans une optique de simplicité que j’essaye de présenter mes tutoriels. Il est clair qu’il y a des points parfois difficiles à faire comprendre au plus grand nombre, c’est aussi pour cela que je vous invite toujours à me signaler toute incompréhension sur un tutoriel que vous liriez.

C’est aussi pour cela qu’il m’arrive d’avoir des tutoriels complexes, et de les épurer en retirant des éléments que je juge inutiles – au moins dans un premier temps.

Mise à jour

Le tutoriel « jQuery – Effet Smooth Scroll (défilement fluide) » a été mis à jour aujourd’hui même afin de faire bénéficier à sa troisième partie d’une meilleure prise en charge des URL absolues fournies d’un hash (exemple : http://creativejuiz.fr/blog#kiwi).

Effet de défilement au chargement de la page

Pour effectuer un effet de défilement, voilà comment expliciter la chose en français :
« On cherche à obtenir le même résultat qu’au clic sur l’ancre porteuse du lien vers la cible présente dans la barre d’adresse. »

Voir la démonstration

Il nous faut prendre la phrase à l’envers et la transformer en jQuery.
Donc en plusieurs étapes il nous faut :

  1. Récupérer le contenu de la barre d’adresse
  2. Récupérer uniquement le hash
  3. Chercher dans notre document quel élément pour l’attribut href="#hash"
  4. Simuler un clic sur cette élément pour déclencher le défilement

Ok, voici un code qui fait ça :

function trigger_click_for_slide() {
      var the_hash = document.location.hash;
      if(the_hash)
          $('a[href~="'+the_hash+'"]').trigger('click');
}
trigger_click_for_slide();

La ligne 2 nous permet de stocker directement le hash (fin de l’URL) dans une variable.
La ligne 3 permet de vérifier l’existence d’un hash en bout d’URL.
La ligne 4, primordiale, permet de simuler (trigger) l’évènement click sur l’élément porteur d’un href ciblant le hash trouvé dans l’URL.

Pourquoi imiter le clic sur un lien plutôt que d’effectuer directement une animation ?
Pour éviter de réécrire une portion du code, et aussi pour limiter les animations vers les ancres prévues par notre système de navigation.

Ce morceau de code peut être placé après la création d’une des mini fonctions vues dans l’article jQuery – Effet Smooth Scroll (défilement fluide).

Écriture du hash dans l’URL

Ninja portant des hastags-shurikenC’est bien sympa de proposer un défilement au chargement, mais puisque le hash ne s’écrit plus dans la barre d’adresse, comment allez vous faire pour partager une URL fournie d’un hash ?

Il faut le réécrire… oui d’accord, mais comment ?
Si on enlève le return false; en fin de fonction, le défilement va sauter, puis défiler de manière fluide, ou inversement.

Il faut donc le faire une fois l’animation terminée !
Je vous l’avez dit dans le précédent tutoriel à ce sujet, la fonction animate() permet l’accueil d’une fonction de callback.

Nous allons donc créer une fonction au sein du mini plugin vu dans l’ancien article, qui va nous permettre de réécrire le hash dans la barre d’adresse.
La voici :

function write_hash(the_hash) {
	    document.location.hash = the_hash;
}

Ensuite il faut faire appel à cette fonction dans notre plugin dans la partie qui gère l’animation :

$(container).animate({
        scrollTop:$(the_element).offset().top
}, speed, function() {
        write_hash(the_hash);
}); 

Au final, nous avons un code complet qui nous donne :

(function($) {
	$.fn.juizScrollTo = function( speed ) {
		if ( !speed ) var speed = 'slow';
		// coeur du plugin
		return this.each( function() {
			$(this).click( function() {
				var goscroll = false;
				var the_hash = $(this).attr("href");
				var regex = new RegExp("(.*)\#(.*)","gi");
				if ( the_hash.match("\#") ) {
					the_hash = the_hash.replace(regex,"$2");
					if($("#"+the_hash).length>0) {
						the_element = "#" + the_hash;
						goscroll = true;
					}
					else if ( $("a[name=" + the_hash + "]").length>0 ) {
						the_element = "a[name=" + the_hash + "]";
						goscroll = true;
					}
					if ( goscroll ) {
						var container = 'html';
						if ( $.browser.webkit ) container = 'body';
						$(container).animate( {
							scrollTop: $(the_element).offset().top
						}, speed, function() {
							tab_n_focus(the_hash)
							write_hash(the_hash);
						});
						return false;
					}
				}
			});
		});
		// fonctions
		// écriture du hash
		function write_hash( the_hash ) {
			document.location.hash =  the_hash;
		}
		// accessibilité au clavier
		function tab_n_focus( the_hash ) {
			$(the_hash).attr('tabindex','0').focus().removeAttr('tabindex');
		}
	};
	// appel de la fonction sur toutes les ancres !
	$('a').juizScrollTo('slow');
	// fonction de slide au chargement
	function trigger_click_for_slide() {
		var the_hash = document.location.hash;
		if ( the_hash )
			$('a[href~="'+the_hash+'"]').trigger('click');
	}
	trigger_click_for_slide();
})(jQuery)

Voilà… je crois que nous avons un code plutôt complet pour ce type d’effet :

  • Gestion des URLs relatives et absolutes
  • Navigation au clavier
  • Réécriture du hash dans l’URL (pratique pour le partage d’une info précise)
  • Effet smoothscroll au chargement de la page (si on cible quelque chose sur la page via l’URL)

N’hésitez pas à laisser un commentaire pour toute remarque sur ce code, problème rencontré, etc…

Merci pour votre lecture et à la prochaine.

15 commentaires et un trackback sur “[Mise à jour] jQuery – Effet smoothscroll au chargement de la page”

  1. Xis dit :
    23 novembre 2011

    Ça l air plutôt sympa comme effet et ton tuto semble très explicite. Je relirais ton tuto à tete reposé. Àpres 4h de sommeil avec le ptit monstre, les choses se brouilles un peu quand meme … :-)

  2. Geoffrey dit :
    23 novembre 2011

    Ah ah ! Tu nages dans le brouillard ! :p
    Merci pour le coup d’œil à venir, je suis ouvert à toute remarque sur le fond comme sur la forme :)
    Bon courage.

  3. Birken dit :
    16 décembre 2011

    Pourquoi ne pas se servir de la propriété location.hash plutôt que des expressions régulières ?

    http://www.w3schools.com/jsref/prop_loc_hash.asp

  4. Geoffrey dit :
    16 décembre 2011

    @Birken : merci pour cette remarque.
    J’avais le souvenir, peut-être à tort, que IE7 avait un problème d’interprétation de location.hash. Je n’ai donc pas pris la peine de tester, la solution regex me semblait convenir ici.
    Je ferai un essai dans le week-end, car ça pourrait davantage simplifier le code ;)

    Merci.

  5. Birken dit :
    17 décembre 2011
  6. Geoffrey dit :
    17 décembre 2011

    Merci pour cette information Birken.
    Je corrige mon code en conséquence ;)

  7. François "cahnory" Germain dit :
    12 janvier 2012

    Joli tuto, j’avais fait un ptit plugin sur le sujet. Je crois qu’il a un petit souci de compatibilité sur un IE (faudrait que je me repenche dessus).

    http://project.cahnory.fr/jquery.scrollIn/

  8. Geoffrey dit :
    12 janvier 2012

    Hey sympa :)
    Merci pour le partage.

  9. Ricardo dit :
    10 février 2012

    Merci pour ce tuto.
    Je l’ai adapté pour que le container soit paramétrable pour que l’effet smooth fonctionne aussi dans un div. Du coup, je peux gérer plusieurs scrollbars.
    Pour mon cas, j’ai changé le scrollTop en scrollLeft.
    En conséquence, mon scrollLeft devient :
    scrollLeft: $(the_element).offset().left – $(container).children().offset().left

  10. Stéphane dit :
    11 février 2012

    Je n’ai pas lu le tuto en entier mais si je ne me trompe pas, le résultat final est le même que propose le plugin jQuery « ScrollTo » ?

  11. Geoffrey dit :
    11 février 2012

    Bonjour,
    Je n’ai pas lu tout ton commentaire mais je pense que tu n’as pas lu tout l’article.
    Merci ;)

  12. Stéphane dit :
    11 février 2012

    Après lecture complète :

    Ce n’engage que moi mais le plugin jQuery ScrollTo avec éventuellement le plugin jQuery Ascensor, nous permet d’obtenir un résultat plus « propre » que l’exemple de démonstration.

    http://www.kirkas.ch/ascensor/

    Aucun rapport avec ce tutoriel, mais l’ouverture dans une nouvelle fenêtre pour l’exemple de démonstration permettrait une meilleure navigation pour ne pas dire « experience utilisateur ».

  13. Geoffrey dit :
    11 février 2012

    Je te remercie pour ta lecture et ton avis, mais je t’avoue que certaines choses m’échappent :

    • Pourquoi comparer des plugins à un tutoriel ? Les deux formes n’ont pas le même but. Le tutoriel permet de mieux appréhender un langage, tandis que le plugin s’installe et c’est tout.
    • Pourquoi comparer deux outils qui n’ont pas la même vocation ? Le mien à pour but de faire une chose, et je pense qu’il le fait bien. Comme le montre le commentaire de Ricardo, il permet également la personnalisation puisque le code est « ouvert ». (d’ailleurs merci pour ton retour d’expérience Ricardo)
    • Pourquoi charger 4 fichiers JS (jQuery, jQuery.scrollTo, jQuery.ascensor, fichier perso) pour un effet si simple quand deux suffisent dans le cadre de l’animation que je propose ? Comme sur ton portfolio, charger autant de fichiers inutilement est absurde, surtout pour ce simple effet. (d’ailleurs si je veux partager uniquement ton portfolio à un ami, je ne peux pas… mauvaise expérience utilisateur)
    • En quoi mon résultat n’est pas propre ?
      • Chez moi si JS est désactivé, mon système d’ancre fonctionne toujours.
      • Si je partage une URL, je peux cibler un endroit précis.
      • Si je navigue sur smartphone, ça fonctionne.

    Concernant ta dernière remarque, on voit là un défaut de maturité de ta réflexion. En quoi imposer un mode de navigation permet de proposer une meilleure expérience utilisateur ? Si l’utilisateur veut ouvrir la démonstration dans un nouvel onglet, il le fait par lui même.
    Comment fait l’utilisateur pour ouvrir le lien dans le même onglet si je le force à faire autrement ?

    Je suis ouvert à toute explication sur le terme trop vague que tu énonces : « propre ».

    Merci et bonne soirée.

  14. Stéphane dit :
    12 février 2012

    - Pourquoi comparer des plugins à un tutoriel ?

    Ce n’est pas vraiment le tutoriel en lui même que je compare mais le résultat final (visuel).

    - Pourquoi comparer deux outils qui n’ont pas la même vocation ?

    Selon le niveau de la personne, elle peut être plus ou moins effrayée par toutes ces lignes de codes et ne cherchera pas à décrypter. C’est pourquoi, j’ai « soumis » deux plugins. Après je suis entièrement d’accord, celui qui souhaite vraiment mettre les mains dans le code, l’améliorer à sa sauce ou comprendre comment ça marche, ce tutoriel est juste parfait.

    - Pourquoi charger 4 fichiers JS … pour un effet si simple quand deux suffisent dans le cadre de l’animation que je propose ?

    Si l’effet final est exactement celui que propose ton tutoriel, il est clair qu’il vaut mieux utiliser 1 seul fichier JS (ton code). ScrollTo et Elevator proposent pas mal d’options super intéressantes et que l’on peut paramétrer très facilement. Sur un gros projet, bien sur ce n’est pas le bienvenu.

    - d’ailleurs si je veux partager uniquement ton portfolio à un ami, je ne peux pas…

    Mon but n’est pas que l’on partage uniquement une section du site mais le site entier.

    - Chez moi si JS est désactivé, mon système d’ancre fonctionne toujours.

    Chez moi aussi ;-) . J’ai juste mis un « return false; » pour qu’il n’y ait uniquement le partage de l’URL sans ancre.

    Donc en clair, selon l’objectif et le type du projet de chacun, il peut être bon de connaitre ton code ou bien ces deux plugins (ScrollTo marche très bien sans Elevator, mais pas l’inverse).

    Bonne soirée.

  15. Geoffrey dit :
    12 février 2012

    Alors merci pour cette présentation, même si elle était déjà faite dans la première partie du tutoriel :
    http://www.creativejuiz.fr/blog/tutoriels/jquery-effet-smooth-scroll-defilement-fluide

    Au moins elle sera également lisible sur cette page.

    J’essaye généralement de ne pas être trop centré sur mes propres codes et présenter des alternatives à mes lecteurs.

    Concernant le problème de JS désactivé, je parlais de la page de démonstration de Ascensor. J’avoue ne pas avoir testé chez toi.

    Merci pour ton commentaire.
    Bonne continuation.

    PS: tu as une erreur de logique sur un de tes cercles en canvas sur ton portfolio, relis bien les pourcentages.

Laisser un commentaire

Les sites qui en parlent

 
Le studio web