Demo : un lecteur audio codé avec jquery

Ce code utilise jquery pour afficher un lecteur avec une barre de lecture, bouton play, récupération d’un titre et d’un auteur.

Précédent | 8/8

Html 5 permet enfin l’affichage d’un lecteur audio sans passer par un plugin quicktime ou flash, mais pose des problèmes nouveaux. Le lecteur de base peut être obtenu avec un code simple, par exemple :

<audio controls>
<source src="montitre.mp3" type="audio/mp3">
</audio>

Mais ce lecteur est construit par défaut par le navigateur, et manque un peu d’élégance. Si on veut personnaliser le lecteur, il faut le faire avec un code html accompagné de fonctions en javascript qui peuvent rebuter plus d’un graphiste.

Un lecteur pour l’exemple

Voici donc un exemple de code permettant d’afficher un lecteur. Considérant que le lecteur flash appartient désormais à l’histoire du web mais plus à son actualité, il n’y a pas de fallback (lecteur de secours) en flash.
Le lecteur ressemblera à ça :

Placer le code html

Le lecteur est donc un mélange de html, de css et de javascript. La première étape est toujours de placer un code html fonctionnel :

<audio class="lecteur-son" controls data-titre="Groove" data-auteur="Auteur inconnu" data-illustration="TR-153.jpg">
               <source src="groove.mp3" type="audio/mp3">
</audio>

Ce code est dégradable, ce qui signifie que en absence de javascript, le son pourra être joué avec le lecteur de base du navigateur. Remarquez trois attribut commençant par "data". Ce sont des attributs qui permettent d’ajouter au lecteur un titre, l’auteur et le mettre une illustration en fond du lecteur.

On place ensuite le code css lié au lecteur qui sera créé par le futur code javascript, dans une feuille de style externe ou une balise <style> :

/* player son : les css */

.wrapper-son {
   position: relative;
   background-color:rgba(255,255,255, 0.8);
   padding:6px;
   font-family:helvetica,sans-serif;
   box-shadow: 0 0 10px rgba(0,0,0,0.2);
   background-size: cover;
   background-position: center center;
   width:100%;
   box-sizing: border-box;
}
.boutons-fond {
   background-size: cover;
   background-position: center center;
   background-repeat: no-repeat;
   background-color:#ddd;
}
.bouton {
   font-size:14px;
   padding:60px 20px;
   text-indent: -9999px;
   color:#fff;
   text-align: center;
   letter-spacing: 0.1em;
   cursor: pointer;
   text-transform: uppercase;
   text-shadow: 0 0 3px #000;
   background-position: center center;
   background-repeat: no-repeat;
   opacity:0.5;
}
.bouton:hover {
   opacity:1;
}
.bouton.play {
   background-image:url(play-circle.svg);
}
.bouton.pause {
   background-image:url(pause-circle.svg);
}
.son-info {
   font-size:11px;
   padding:6px;
   color:#666;
   display:flex;
   flex-wrap: wrap;
}
.son-info .played, .son-info .duration {
   width:50%;
}
.son-info .titre {
   width:100%;
   padding-top:4px;
   text-align:center;
   font-weight:bold;
}
.son-info .auteur {
   font-weight:normal;
   display:block;
   padding-top:4px;
}
.son-info .duration {
   text-align:right;
}
.timeline {
   box-sizing: border-box;
   background-color: #d6d6d6;
   cursor:col-resize;
}
.bar-played {
   height:100%;
   width:0;
   background-color:#777777;
   height:10px;
}

Placer le javascript

Le code javascript peut être placé dans la page ou dans un fichier externe .js. Il ne faut pas oublier de charger auparavant le code de jquery.

Ce code cache le lecteur d’origine, et crée une structure html, avec un espace pour le bouton play/pause, l’affichage de la durée totale et de la durée de lecture écoulée, le titre et le nom de l’auteur. Ces deux dernières informations doivent être renseignées dans le tag audio d’origine sous la forme de deux attribut "data". Voir le code html décrit plus haut.

Une fois le code html créé, le code récupère dans les métadonnées du fichier la durée en secondes du son et l’affiche dans le code html du lecteur et attend un clic pour lancer le son ou déplacer la tête de lecture.

Des actions en clic sont ajoutées sur le bouton "play" et "pause", une action est ajoutée sur la barre de lecture, qui permet au son de sauter d’un endroit à l’autre en clic. Puis deux "listeners" sont ajoutés. Un event listener est une fonction qui est appelée aussi vite que possible tant qu’une action a lieu. Dans notre cas, le premier eventListener récupère la durée totale du son dès que les "métadatas" sont lues. Le deuxième concerne la lecture elle-même : lorsque le son est joué, on veut pouvoir afficher les secondes écoulées et faire avancer la barre de lecture. Pour cela, le code
audio.addEventListener("timeupdate", function(){});
est ajouté, "timeupdate" appellant une fonction quand le son est joué. La fonction est appelée plusieurs fois par seconde, ce qui lui permet d’être parfaitement à jour.

Une fonction a été ajoutée en fin de code : elle permet de transformer l’affichage du temps, qui par défaut est en secondes brutes, par exemple 120 secondes, en un temps plus lisible, dans notre cas 2:00 pour deux minutes.

/*
prend en charge le lecteur son
structure html :
<audio class="lecteur-son" controls data-titre="Titre du morceau" data-auteur="auteur du morceau" data-illustration="image.jpg">
        <source src="song.mp3" type="audio/mp3">
</audio>
*/
$(document).ready(function(){
   $("audio.lecteur-son").each(function(i){
       var audio=$(this).get(0);
       // ajouter le titre
       var infos="";
       var drag=false;
       
       $(this).removeAttr("controls");
       $(this).wrap("<div class='wrapper-son' id='lecteur-"+i+"'></div>");
       var lecteur=$(this).parent();
       lecteur.append("<div class='boutons-fond'><div class='bouton play'>Play</div><div class='bouton pause'>Pause</div></div><div class='timeline'><div class='bar-played'></div></div><div class='son-info'><div class='played'>00:00</div><div class='duration'>00:00</div></div>");
       
       if(audio.hasAttribute("data-titre")){ infos=$(audio).attr("data-titre"); }
       if(audio.hasAttribute("data-auteur")){
           var auteur=$(audio).attr("data-auteur");  
           infos+="<span class='auteur'>"+auteur+"</span> ";
       }
       if(infos.length > 0){
           lecteur.find(".son-info").append("<div class='titre'>"+infos+"</div>");
       }
       // image éventuelle
       if(audio.hasAttribute("data-illustration")){ lecteur.find(".boutons-fond").css("background-image","url("+$(audio).attr("data-illustration")+")"); }

       // bouton play et pause
       lecteur.find(".play").click(function(){
           audio.play();
           $(this).hide();
           $(this).siblings(".pause").show();
       });
       lecteur.find(".pause").hide().click(function(){
           audio.pause();
           $(this).hide();
           $(this).siblings(".play").show();
       });
       // clicker sur la barre de temps et dragger
       lecteur.find(".timeline").click(function(e){
           var lt=$(this).innerWidth();
           var x = e.pageX - $(this).offset().left;
           var jp=audio.currentTime=audio.duration*(x/lt);
       }).mousedown(function() {
           drag=true;
       }).mouseup(function(){
           drag=false;
       }).mousemove(function(e){
           if(drag){
           var lt=$(this).innerWidth();
           var x = e.pageX - $(this).offset().left;
           var jp=audio.currentTime=audio.duration*(x/lt);
           }
       });

       // charger la durée qu démarrage
       audio.addEventListener('loadedmetadata',function(){
           lecteur.find('.duration').html(formate_temps(audio.duration));
       },false);
       // montrer les infos pendant la lecture
       audio.addEventListener("timeupdate", function() {
           // ligne du temps
           var pc=(audio.currentTime/audio.duration)*100;
           lecteur.find(".timeline .bar-played").css("width",pc+"%");
           lecteur.find('.played').html(formate_temps(audio.currentTime));
       }, false);

   });
});

// Transformer la durée (en secondes brutes, 221 par ex)
// vers une structure minutes/secondes (3:41 par ex)
function formate_temps(temps){
   s = parseInt(temps % 60);
   m = Math.floor( temps / 60 ) % 60;
   s = s < 10 ? "0"+s : s;
   m = m < 10 ? "0"+m : m;
   return m+":"+s;
}