Trucsweb.com

Trucsweb.com

Javascript

Sans jQuery

RDFFav

Défilement doux ou le « Smooth Scrolling » en pur JavaScript

Je n’ai fait que traduire intégralement le code jQuery en pur JavaScript.scrollDéfilement doux ou le « Smooth Scrolling » en pur JavaScript

ATTENTION Les dernières versions du brillant Google Chrome plantent à cause de ce script!! Résultat, les ancres (#ancre) ne fonctionne pas bien voir pas du tout. Notez que je n’ai aucun problème avec Firefox. Les forums sont remplis de messages et de webmestres aux abois, mais aucune solution ne semble régler ce problème de taille! Alors, éviter à tout prix ce script, car malheureusement le pisteur Google Chrome (que je déteste) est largement le navigateur le plus utilisé dans le monde...

Toute fois, le CSS3 a maintenant une instruction qui fait précisément la même chose sans une ligne de JavaScript !

html {
  scroll-behavior: smooth;
}
Défilement doux (Dunes du Sahara) (Auteur : Photo : Ivan Losar)

Malgré son côté accessoire, esthétique, c’est un effet que je trouve ergonomique. La transition plus naturelle (personne ne tourne les pages d’un livre en un clin d’oeil!) permet de suivre la navigation sans perdre le fil, sans choque neural. La concentration reste fluide.

Je n’ai fait que traduire intégralement le code jQuery en pur JavaScript. Passer les hyperliens de la page en revue pour leur ajouter la capture de l’événement « click » sans jQuery ne date pas d’hier. Ce qui n’est pas le cas de l’animation, plus difficile à reproduite.

Ici il n’est pas question de nouvelles animations ou de transitions CSS3 mais bien de pur JavaScript et plus précisément le classique « compteur » ou « timer » avec setTimeout pour défiler jusqu’en haut ...petit à petit, laissant l’impression d’un glissement doux. Un code assez répandu par ailleurs. Mais je suis tombé sur un petit script de Forestrf qui calcul pour nous plusieurs effets de transition. J’ai donc combiné les deux scripts.

Exemple avec le bouton retour en haut

Copier ce code dans votre document HTML :

<script>
// Par Oznog, trucsweg.com
// http://trucsweb.com/tutoriels/javascript/defilement_doux
document.addEventListener('DOMContentLoaded', function() {
  var aLiens = document.querySelectorAll('a[href*="#"]');
  for(var i=0, len = aLiens.length; i<len; i++) {
    aLiens[i].onclick = function () {
      if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
        var target = this.getAttribute("href").slice(1);
        if (target.length) {
          scrollTo(document.getElementById(target).offsetTop, 1000);
          return false;
        }
      }
    };
  }
});
//Exemple de : Forestrf
// http://jsfiddle.net/forestrf/tPQSv/2/
function scrollTo(element, duration) {
  var e = document.documentElement;
  if(e.scrollTop===0){
    var t = e.scrollTop;
    ++e.scrollTop;
    e = t+1===e.scrollTop--?e:document.body;
  }
  scrollToC(e, e.scrollTop, element, duration);
}

function scrollToC(element, from, to, duration) {
  if (duration < 0) return;
  if(typeof from === "object")from=from.offsetTop;
  if(typeof to === "object")to=to.offsetTop;
  scrollToX(element, from, to, 0, 1/duration, 20, easeOutCuaic);
}

function scrollToX(element, x1, x2, t, v, step, operacion) {
  if (t < 0 || t > 1 || v <= 0) return;
  element.scrollTop = x1 - (x1-x2)*operacion(t);
  t += v * step;
  setTimeout(function() {
    scrollToX(element, x1, x2, t, v, step, operacion);
  }, step);
}

function easeOutCuaic(t){
  t--;
  return t*t*t+1;
}
</script>
Toutes les fonctions Forestrf
function linearTween(t){
	return t;
}

function easeInQuad(t){
	return t*t;
}

function easeOutQuad(t){
	return -t*(t-2);
}

function easeInOutQuad(t){
	t/=0.5;
	if(t<1)return t*t/2;
	t--;
	return (t*(t-2)-1)/2;
}

function easeInCuaic(t){
	return t*t*t;
}

function easeOutCuaic(t){
	t--;
	return t*t*t+1;
}

function easeInOutCuaic(t){
	t/=0.5;
	if(t<1)return t*t*t/2;
	t-=2;
	return (t*t*t+2)/2;
}

function easeInQuart(t){
	return t*t*t*t;
}

function easeOutQuart(t){
	t--;
	return -(t*t*t*t-1);
}

function easeInOutQuart(t){
	t/=0.5;
	if(t<1)return 0.5*t*t*t*t;
	t-=2;
	return -(t*t*t*t-2)/2;
}

function easeInQuint(t){
	return t*t*t*t*t;
}

function easeOutQuint(t){
	t--;
	return t*t*t*t*t+1;
}

function easeInOutQuint(t){
	t/=0.5;
	if(t<1)return t*t*t*t*t/2;
	t-=2;
	return (t*t*t*t*t+2)/2;
}

function easeInSine(t){
	return -Mathf.Cos(t/(Mathf.PI/2))+1;
}

function easeOutSine(t){
	return Mathf.Sin(t/(Mathf.PI/2));
}

function easeInOutSine(t){
	return -(Mathf.Cos(Mathf.PI*t)-1)/2;
}

function easeInExpo(t){
	return Mathf.Pow(2,10*(t-1));
}

function easeOutExpo(t){
	return -Mathf.Pow(2,-10*t)+1;
}

function easeInOutExpo(t){
	t/=0.5;
	if(t<1)return Mathf.Pow(2,10*(t-1))/2;
	t--;
	return (-Mathf.Pow(2,-10*t)+2)/2;
}

function easeInCirc(t){
	return -Mathf.Sqrt(1-t*t)-1;
}

function easeOutCirc(t){
	t--;
	return Mathf.Sqrt(1-t*t);
}

function easeInOutCirc(t){
	t/=0.5;
	if(t<1)return -(Mathf.Sqrt(1-t*t)-1)/2;
	t-=2;
	return (Mathf.Sqrt(1-t*t)+1)/2;
}

Pour aller encore plus loin dans les effets et les animations sans jquery, voir les fonctions « Easing » de Robert Penner’s

Équivalent jQuery

Ceci n’enlève en rien au jQuery, indispensable en d’autre circonstance. Vaut mieux alors garder la même philosophie. Tout le monde connait d’ailleurs le script « Smooth Scrolling » disponible sur CSS-Tricks.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});
Références
, Analyste programmeurConception oznogco multimédia (http://oznogco.com), Trucsweb
Dernière mise à jour :

Commentaires

  • Salut, Je suis en train de faire un smooth scroll également, mais je cherche des trucs pour combler les très, très mauvaises performances de cette méthode sur Android avec des pages au rendu plus complexe (background fixes, semi opacité, etc etc...). As-tu également rencontré ce genre de problèmes ? J'en suis arrivé à utiliser les requestAnimationFrame tant les perfs étaient basses... Et je ne parle même pas des canvas !
    64x64
    Gerkin
    Date (GMT) : 2016-03-23 10:20:33 (UTC +0000)
    • Salut, Je n'ai malheureusement pas de solution miracle. Et je confirme la piètre performance d'Adroid dès qu'il y a un effet Parallaxe ou même un arrière-plan fixe. Je pense que c'est essentiellement une question de ressources, il n'y en a pas assez! Alors à mon avis une animation avec les « keys frames » ne règlera rien. Ça passe dans une section de page, mais dans l'ensemble de la page, l'indigestion guette! Keep It simple, c'est tout ce que je peux dire. En général ce genre de manipulation fonctionne avec de nombreuses librairies, simplement pour mettre à niveau la compatibilité ou pour simplifier le travail. Ce qui augmente le stress sur le navigateur client. Un contenu caché gigantesque, des requêtes serveur nombreuses, sur plusieurs serveurs à la foi, mélange de protocoles HTTPS et HTTP. Et ce n'est pas fini, il faut le traiter ce code. Le navigateur commence par la base, puis on réinvente le CSS, au début en le remettant à zéro, ensuite en lui redonnent ses bases pour ensuite tout refaire une dernière fois selon son cadriciel. Pour enfin entrer du CSS en-ligne (inline). Et on a encore rien fait! À l'époque nous avions un site normal et un second pour mobile, avec la technologie Wap. Depuis le CSS 3 et les « médiaquerys » on a la chance de travailler un seul site. Idéalement avec la méthode « Mobile first ». Mais le mobile reste un appareil aux capacités limitées alors qu'on se retrouve avec des sites beaucoup trop lourd. Personnellement, je retire tout fond fixe sur les petites résolutions. Mais tout porte à croire que nous allons revenir aux deux versions de site web. Déjà les écrans « Retina » obligent à servir deux, voir trois images selon la résolution (2x, 3x et même 4x). Mais en plus, Google vient tout juste de sortir son projet AMP qui est justement basé sur l'idée qu'un site conventionnel est beaucoup trop lourd sur un mobile ou sur une tablette. Google a dû faire l'expérience de son Android ; -) Donc à moins de développer consciemment, avec parcimonie et souci d'économie, vaut mieux faire un site spécifique pour les petits appareils. Et puisque Big Brother ne risque pas de disparaitre avant longtemps, aussi bien y aller directement en AMP (eh oui une énième librairie) qui offre un tout nouveau panier de snipets (pour ne pas dire de crabe!). Mais force est de constater qu'Android est très frustrant... D'ailleurs un portable Mac bas de gamme en souffre autant! Ironiquement, la tablette et son (gyroscope) permet des fonctionnalités très intéressantes pour les effets parallaxe! En attendant, élimine les mobiles tout simplement : // jQuery $(document).ready(function(){ if (/Android|BlackBerry|iPhone|iPad|iPod|webOS/i.test(navigator.userAgent) === false) { // Effet Parallaxe sur support non-mobile twParallaxe(); }​ }); Ciao
      64x64
      oznog
      Date (GMT) : 2016-03-23 12:26:39 (UTC +0000)


    • Bonjour, J'aime beaucoup le script "http://www.trucsweb.com/tutoriels/javascript/retour-haut/". Mais je suis incapable d'insérer celui ci a l'intérieur car mon javascript es plus que médiocre et après moulte tentative je n'obtiens aucun résultat. Je te serai très reconnaissant si tu pouvais faire un autre tuto avec les 2 imbriqués l'un dans l'autre. Merci beaucoup d'avance Eric
      64x64
      Eric Gayraud
      Date (GMT) : 2016-08-10 23:21:11 (UTC +0000)
      • Salut, Il suffit de regarder le code source de l'exemple du iFrame. Les deux sont déjà combinés. Et dans mon exemple, j'ai simplement collé les deux scripts. On pourrait véritablement les combiner, par exemple avec une seule capture du chargement. document.addEventListener('DOMContentLoaded', function() {... Mais voilà le code : <!DOCTYPE html> <html lang="fr-CA"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Défilement doux ou le « Smooth Scrolling » en pur JavaScript (Trucsweb.com)</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="robots" content="noindex,nofollow"> <meta name="author" content="Django Oznog Blais, Trucsweb.com"> <style> a#cRetour{ border-radius:3px; padding:10px; font-size:15px; text-align:center; color:#fff; background:rgba(0, 0, 0, 0.25); position:fixed; right:20px; opacity:1; z-index:99999; transition:all ease-in 0.2s; backface-visibility: hidden; -webkit-backface-visibility: hidden; text-decoration: none; } /* Flèche */ a#cRetour:before{ content: "\25b2"; } a#cRetour:hover{ background:rgba(0, 0, 0, 1); transition:all ease-in 0.2s; } a#cRetour.cInvisible{ bottom:-35px; opacity:0; transition:all ease-in 0.5s; } a#cRetour.cVisible{ bottom:10px; opacity:1; } html,body { height:100%; margin:0; } .content { height:100%; min-height:100%;/*for mozilla*/ } html>body .content { height:auto; } #section1 { /* background: url(https://dl.dropboxusercontent.com/u/3400459/CodePen/Fullscreen-DIVs/dark-red.png) center center no-repeat scroll #520E24; */ width:100%; text-align: center; vertical-align: middle; /* fallback for non-Flexbox browsers */ display: inline-block; /* Flexbox browsers */ display: -webkit-inline-box; display: -moz-inline-box; display: -ms-inline-flexbox; display: -webkit-inline-flex; display: inline-flex; /* vertical centering for legacy, horizontal centering for modern */ -webkit-box-pack: center; -moz-box-pack: center; -ms-flex-pack: center; -webkit-justify-content: center; justify-content: center; /* modern Flexbox only */ -ms-flex-align: center; -webkit-align-items: center; align-items: center; /* legacy Flexbox only */ -webkit-box-orient: vertical; -moz-box-orient: vertical; background-color: #ff9933; font-size:6em; } #section2 { /* background: url(https://dl.dropboxusercontent.com/u/3400459/CodePen/Fullscreen-DIVs/red.png) center center no-repeat scroll #8F2041; */ background-color: #c6c3bd; font-size:6em; display: flex; justify-content: center; align-items: center; } #section3 { /* background: url(https://dl.dropboxusercontent.com/u/3400459/CodePen/Fullscreen-DIVs/dark-orange.png) center center no-repeat scroll #DC554F; */ background-color: #d6d3ce; font-size:6em; display: flex; justify-content: center; align-items: center; } #section4 { /* background: url(https://dl.dropboxusercontent.com/u/3400459/CodePen/Fullscreen-DIVs/orange.png) center center no-repeat scroll #FF905E; */ background-color: #eeeeee; font-size:6em; display: flex; justify-content: center; align-items: center; } #section5 { /* background: url(https://dl.dropboxusercontent.com/u/3400459/CodePen/Fullscreen-DIVs/yellow.png) center center no-repeat scroll #FFDB77; */ background-color: #ffffff; font-size:6em; display: flex; justify-content: center; align-items: center; } </style> </head> <body style="height:100%" name="haut" id="haut"> <div class="content" id="section1">1</div> <div class="content" id="section2">2</div> <div class="content" id="section3">3</div> <div class="content" id="section4">4</div> <div class="content" id="section5">5</div> <div><a id="cRetour" class="cInvisible" href="#haut"></a></div> <script> document.addEventListener('DOMContentLoaded', function() { window.onscroll = function(ev) { document.getElementById("cRetour").className = (window.pageYOffset > 100) ? "cVisible" : "cInvisible"; }; }); document.addEventListener('DOMContentLoaded', function() { var aLiens = document.queryselectorAll('a[href*="#"]'); for(var i=0, len = aLiens.length; i<len; i++) { aLiens[i].onclick = function () { if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) { var target = this.getAttribute("href").slice(1); if (target.length) { scrollTo(document.getElementById(target).offsetTop, 1000); return false; } } }; } }); function scrollTo(element, duration) { var e = document.documentElement; if(e.scrollTop===0){ var t = e.scrollTop; ++e.scrollTop; e = t+1===e.scrollTop--?e:document.body; } scrollToC(e, e.scrollTop, element, duration); } function scrollToC(element, from, to, duration) { if (duration < 0) return; if(typeof from === "object")from=from.offsetTop; if(typeof to === "object")to=to.offsetTop; scrollToX(element, from, to, 0, 1/duration, 20, easeOutCuaic); } function scrollToX(element, x1, x2, t, v, step, operacion) { if (t < 0 || t > 1 || v <= 0) return; element.scrollTop = x1 - (x1-x2)*operacion(t); t += v * step; setTimeout(function() { scrollToX(element, x1, x2, t, v, step, operacion); }, step); } //BON function easeOutCuaic(t){ t--; return t*t*t+1; } </script> </body> </html>
        64x64
        OZNOG
        Date (GMT) : 2016-08-30 13:2:26 (UTC +0000)


      Ajouter un commentaire
      Votre adresse de courriel ne sera pas publiée. * L'astérisque indique les champs obligatoires.
      Votre évaluation du tutoriel

      9/10 sur 1 revues.
             Visites : 32463 - Pages vues : 33657
      X

      Trucsweb.com Connexion

      Connexion

      X

      Trucsweb.com Mot de passe perdu

      Connexion

      X

      Trucsweb.com Conditions générales

      Conditions

      Responsabilité

      La responsabilité des Trucsweb.com ne pourra être engagée en cas de faits indépendants de sa volonté. Les informations mises à disposition sur ce site le sont uniquement à titre purement informatif et ne sauraient constituer en aucun cas un conseil ou une recommandation de quelque nature que ce soit.

      Aucun contrôle n'est exercé sur les références et ressources externes, l'utilisateur reconnaît que les Trucsweb.com n'assume aucune responsabilité relative à la mise à disposition de ces ressources, et ne peut être tenue responsable quant à leur contenu.

      Droit applicable et juridiction compétente

      Les règles en matière de droit, applicables aux contenus et aux transmissions de données sur et autour du site, sont déterminées par la loi canadienne. En cas de litige, n'ayant pu faire l'objet d'un accord à l'amiable, seuls les tribunaux canadien sont compétents.

      X

      Trucsweb.com Trucsweb

      X

      Trucsweb.com Glossaire

      X

      Trucsweb.com Trucsweb

      X

      Trucsweb.com Trucsweb

      Conditions

      Aucun message!

      Merci.

      X
      Aucun message!
      X

      Trucsweb.com Créer un compte

      Créer un compte

      .
      @