Maison > interface Web > Tutoriel H5 > Implémenter un exemple de lecteur de musique HTML5

Implémenter un exemple de lecteur de musique HTML5

零下一度
Libérer: 2017-07-23 13:28:16
original
6186 Les gens l'ont consulté

Points techniques : ES6+Webpack+HTML5 Audio+Sass

Ici, nous allons apprendre étape par étape comment implémenter un lecteur de musique H5 à partir de zéro.

Jetons d'abord un coup d'œil à l'implémentation finale : lien de démonstration

Puis passons aux choses sérieuses :

  1. Pour créer un lecteur de musique dont vous avez besoin Je connais très bien la façon dont l'audio est lu sur le Web. La balise audio HTML5
    est généralement utilisée. Concernant la balise audio, elle possède un grand nombre de propriétés, de méthodes et d'événements. .

    Attributs :
    src : obligatoire, source audio ;
    contrôles : commun, le panneau de contrôle audio par défaut du navigateur sera affiché après le réglage et la balise audio sera masquée par défaut si elle n'est pas définie ;
    lecture automatique : commune, lire automatiquement l'audio après le réglage (non pris en charge par le terminal mobile) ;
    boucle : commune, l'audio sera lu en boucle après le réglage
    préchargement : commun, définir le préchargement audio (non pris en charge par le mobile) ; terminal);
    volume : rare , définit ou renvoie la taille de l'audio, la valeur est un nombre à virgule flottante entre 0 et 1 (non pris en charge par les terminaux mobiles
    muted : rare, définit ou renvoie l'état muet );
    duration : rare, renvoie la durée de l'audio ;
    currentTime : rare, définit ou renvoie l'heure de lecture actuelle ;
    paused : rare, renvoie l'état de lecture actuel, s'il faut mettre en pause ;
    buffered : rare ; , un objet TimeRanges contenant des informations de période mises en mémoire tampon, c'est-à-dire la progression du chargement. Cet objet contient un attribut length, qui renvoie un nombre commençant à 0 pour indiquer combien de segments audio sont actuellement mis en mémoire tampon. Il contient également deux méthodes, start et end, qui doivent chacune être transmises dans un paramètre, c'est-à-dire quel segment du fichier ; l’audio a été chargé à partir de 0. start renvoie l'heure de début du segment et end renvoie l'heure de fin du segment. Par exemple : passez 0, le début du premier paragraphe est 0, l'heure de fin est 17, l'unité est en secondes ; l'attribut
    est introduit ici, il peut y avoir des attributs moins couramment utilisés tels que : playbackRate, etc. ., pendant la lecture vidéo Il peut être utilisé, mais je ne l'expliquerai pas encore.

    Méthodes :
    play() : Démarrer la lecture audio ;
    pause() : Mettre en pause la lecture audio

    Événement :
    canplay : L'audio actuel peut commencer à jouer ( seule une partie de la mémoire tampon est chargée, mais tout n'est pas chargé
    canplaythrough : peut être lu sans pause (c'est-à-dire que tout l'audio est chargé
    durationchange : la durée de l'audio change
    terminée ); la lecture se termine ;
    erreur : une erreur s'est produite ;
    pause : la lecture est en pause ;
    lecture : la lecture commence
    progression : déclenchée pendant le processus de déclenchement de l'événement, la progression du chargement. peut être obtenu en accédant à l'attribut buffered de l'audio ;
    seek : Déclenché pendant le saut audio, c'est-à-dire lorsque currentTime est modifié
    seeked : Déclenché lorsque le saut audio est terminé, c'est-à-dire lorsque currentTime est modifié ; 🎜>timeupdate : déclenché pendant la lecture audio et l'attribut currentTime est mis à jour de manière synchrone ;
    Les événements sont présentés ici. Il peut y avoir des événements moins couramment utilisés qui ne seront pas encore expliqués.

    Enfin, expliquons le flux d'événements déclenchés par un audio du début du chargement à la fin de la lecture, ainsi que les attributs que nous pouvons opérer à différentes périodes :
    loadstart : démarrer le chargement changement de durée : obtenez la durée de l'audio (l'attribut de durée peut être obtenu à ce moment) ;
    progression : téléchargement audio (sera déclenché avec le processus de téléchargement, et l'attribut mis en mémoire tampon peut être obtenu à ce moment) ; 🎜>canplay : L'audio chargé est suffisant pour commencer la lecture (la lecture sera également déclenchée après chaque pause) ;
    canplaythrough : tous les audios sont chargés
    timeupdate : pendant la lecture (l'attribut currentTime est mis à jour de manière synchrone) ;
    recherche : la progression de la lecture en cours est en cours de modification (c'est-à-dire (pour modifier l'attribut currentTime) );
    recherchée : la modification de la progression de la lecture en cours est terminée ;
    terminée : la lecture est terminée ;
    Ceci est le flux général des événements de l'ensemble de l'audio. Il peut y avoir des événements moins utilisés qui ne sont pas répertoriés.
    Pendant le processus de déclenchement de l'événement, certaines propriétés peuvent être définies avant le début du chargement de l'audio, telles que : les commandes, la boucle, le volume, etc.




    Déterminez la structure globale :
  2. Parce que nous le créons sous forme de plug-in et que nous le publions sur npm pour que d'autres puissent l'utiliser, nous utilisons une approche orientée objet pour l'écriture de code, et parce que les utilisateurs ont des besoins différents, nous concevons Un grand nombre d'API et d'éléments de configuration sont exposés dès le début pour répondre aux besoins de la plupart des utilisateurs.
  3. Parce que je suis plus habitué à la syntaxe d'es6, j'ai développé l'ensemble du processus basé sur es6. En même temps, par souci d'efficacité du développement, j'ai utilisé sass pour écrire du css. dev-server pour compiler es6. Et sass, packaging du projet, construire un serveur local.




  4. Déterminez l'interface utilisateur et l'interaction du joueur :
    Peut-être que chacun a ses propres idées sur l'interface, je n'entrerai donc pas dans les détails ici. Prenons l'interface utilisateur du joueur que j'ai créée comme exemple. décomposez-le

    Depuis l'interface, vous pouvez voir les fonctions les plus basiques requises par un joueur :
    Lecture/pause, reprise/titre de la chanson/affichage du chanteur, barre de progression de lecture/barre de progression de chargement Fonction de fonctionnement / progression, changement de mode de boucle, mise à jour du texte de progression/durée de la chanson, contrôle de la sourdine/du volume, contrôle de l'état d'affichage de la liste, cliquez sur l'élément de la liste pour changer de chanson
    Combiné avec le point de départ de la fourniture des éléments de configuration et des API que nous souhaitons pour répondre aux besoins des utilisateurs, nous pouvons déterminer les éléments de configuration et les éléments d'API exposés que nous souhaitons concevoir :
    Éléments de configuration : si la lecture automatique est activée, l'état d'affichage de la liste de chansons par défaut et les paramètres du mode de boucle par défaut
    API : lecture/pause/basculement, changement de mode de boucle, sourdine/restauration, statut d'affichage de la liste de commutation, chanson précédente/chanson suivante/chanson coupée, destruction de l'instance actuelle


  5. Établir la structure du projet, commencer à coder :
    Parce que nous utilisons webpack, nous emballons le CSS directement dans js afin qu'il puisse être utilisé comme plug-in pour les utilisateurs :

    require('./skPlayer.scss');
    Copier après la connexion

    Extraire les méthodes publiques , il existe de nombreuses méthodes publiques dans le lecteur qui peuvent devoir être extraites, telles que : lorsque vous cliquez sur la barre de progression de la lecture et la barre de progression du volume, vous devez pour calculer la distance entre la souris et l'extrémité gauche de la barre de progression pour le saut de progression. Le temps est obtenu à partir de la durée en secondes. Convertissez l'unité de temps en format d'heure standard, etc. :

    const Util = {
        leftDistance: (el) => {
            let left = el.offsetLeft;
            let scrollLeft;while (el.offsetParent) {
                el = el.offsetParent;
                left += el.offsetLeft;
            }
            scrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft;return left - scrollLeft;
        },
        timeFormat: (time) => {
            let tempMin = parseInt(time / 60);
            let tempSec = parseInt(time % 60);
            let curMin = tempMin < 10 ? (&#39;0&#39; + tempMin) : tempMin;
            let curSec = tempSec < 10 ? (&#39;0&#39; + tempSec) : tempSec;return curMin + &#39;:&#39; + curSec;
        },
        percentFormat: (percent) => {return (percent * 100).toFixed(2) + '%';
        },
        ajax: (option) => {
            option.beforeSend && option.beforeSend();
            let xhr = new XMLHttpRequest();
            xhr.onreadystatechange = () => {if(xhr.readyState === 4){if(xhr.status >= 200 && xhr.status < 300){
                        option.success && option.success(xhr.responseText);
                    }else{
                        option.fail && option.fail(xhr.status);
                    }
                }
            };
            xhr.open(&#39;GET&#39;,option.url);
            xhr.send(null);
        }
    };
    Copier après la connexion
    Afficher le code
    En raison de la conception initiale, en tenant compte du caractère unique du joueur, il est conçu pour qu'une seule instance puisse exister, et une variable globale est définie pour déterminer si l'instance existe actuellement :

    let instance = false;
    Copier après la connexion
    Dans le cas de l'utilisation d'ES6 , nous mettons la logique principale à l'intérieur du constructeur, et mettons la logique hautement polyvalente et API à l'intérieur de la fonction publique :

    class skPlayer {
        constructor(option){
        }
    
        template(){
        }
    
        init(){
        }
    
        bind(){
        }
    
        prev(){
        }
    
        next(){
        }
    
        switchMusic(index){
        }
    
        play(){
        }
    
        pause(){
        }
    
        toggle(){
        }
    
        toggleList(){
        }
    
        toggleMute(){
        }
    
        switchMode(){
        }
    
        destroy(){
        }
    }
    Copier après la connexion
    Afficher le code
    Jugement d'instance, s'il y a un objet vide sans prototype, un objet vide sans prototype est renvoyé, car le constructeur ES6 renvoie une instance avec un prototype par défaut :

            if(instance){
                console.error(&#39;SKPlayer只能存在一个实例!&#39;);return Object.create(null);
            }else{
                instance = true;
            }
    Copier après la connexion
    Éléments de configuration d'initialisation, la configuration par défaut est fusionnée avec la configuration utilisateur :

            const defaultOption = {
                ...
            };this.option = Object.assign({},defaultOption,option);
    Copier après la connexion
    Lier les propriétés communes à l'instance :

            this.root = this.option.element;this.type = this.option.music.type;this.music = this.option.music.source;this.isMobile = /mobile/i.test(window.navigator.userAgent);
    Copier après la connexion
    Certaines propriétés publiques L'interne ce point de l'API pointe vers l'instance par défaut, mais afin de réduire la quantité de code, un ensemble de codes est utilisé pour appeler les fonctions sur l'interface d'opération et l'API lors de la liaison des événements, ce point changera, alors liez-le. via bind. Bien sûr, vous pouvez également utiliser les fonctions fléchées lors de la liaison d'événements :

            this.toggle = this.toggle.bind(this);this.toggleList = this.toggleList.bind(this);this.toggleMute = this.toggleMute.bind(this);this.switchMode = this.switchMode.bind(this);
    Copier après la connexion
    Ensuite, nous utilisons le modèle de chaîne ES6 pour commencer à générer du HTML et l'insérer dans la page :

                this.root.innerHTML = this.template();
    Copier après la connexion
    Ensuite, initialisez. Pendant le processus d'initialisation, les nœuds DOM communs seront liés, les éléments de configuration seront initialisés et l'interface d'opération sera initialisée :

                this.init();
    Copier après la connexion
        init(){this.dom = {
                cover: this.root.querySelector(&#39;.skPlayer-cover&#39;),
                playbutton: this.root.querySelector(&#39;.skPlayer-play-btn&#39;),
                name: this.root.querySelector(&#39;.skPlayer-name&#39;),
                author: this.root.querySelector(&#39;.skPlayer-author&#39;),
                timeline_total: this.root.querySelector(&#39;.skPlayer-percent&#39;),
                timeline_loaded: this.root.querySelector(&#39;.skPlayer-line-loading&#39;),
                timeline_played: this.root.querySelector(&#39;.skPlayer-percent .skPlayer-line&#39;),
                timetext_total: this.root.querySelector(&#39;.skPlayer-total&#39;),
                timetext_played: this.root.querySelector(&#39;.skPlayer-cur&#39;),
                volumebutton: this.root.querySelector(&#39;.skPlayer-icon&#39;),
                volumeline_total: this.root.querySelector(&#39;.skPlayer-volume .skPlayer-percent&#39;),
                volumeline_value: this.root.querySelector(&#39;.skPlayer-volume .skPlayer-line&#39;),
                switchbutton: this.root.querySelector(&#39;.skPlayer-list-switch&#39;),
                modebutton: this.root.querySelector(&#39;.skPlayer-mode&#39;),
                musiclist: this.root.querySelector(&#39;.skPlayer-list&#39;),
                musicitem: this.root.querySelectorAll(&#39;.skPlayer-list li&#39;)
            };this.audio = this.root.querySelector(&#39;.skPlayer-source&#39;);if(this.option.listshow){this.root.className = &#39;skPlayer-list-on&#39;;
            }if(this.option.mode === &#39;singleloop&#39;){this.audio.loop = true;
            }this.dom.musicitem[0].className = &#39;skPlayer-curMusic&#39;;
        }
    Copier après la connexion
    Afficher le code
    Liaison d'événements, principalement la liaison d'événements audio et d'événements du panneau de commande :

                this.bind();
    Copier après la connexion
        bind(){this.updateLine = () => {
                let percent = this.audio.buffered.length ? (this.audio.buffered.end(this.audio.buffered.length - 1) / this.audio.duration) : 0;this.dom.timeline_loaded.style.width = Util.percentFormat(percent);
            };// this.audio.addEventListener('load', (e) => {//     if(this.option.autoplay && this.isMobile){//         this.play();//     }// });this.audio.addEventListener('durationchange', (e) => {this.dom.timetext_total.innerHTML = Util.timeFormat(this.audio.duration);this.updateLine();
            });this.audio.addEventListener('progress', (e) => {this.updateLine();
            });this.audio.addEventListener('canplay', (e) => {if(this.option.autoplay && !this.isMobile){this.play();
                }
            });this.audio.addEventListener('timeupdate', (e) => {
                let percent = this.audio.currentTime / this.audio.duration;this.dom.timeline_played.style.width = Util.percentFormat(percent);this.dom.timetext_played.innerHTML = Util.timeFormat(this.audio.currentTime);
            });//this.audio.addEventListener('seeked', (e) => {//    this.play();//});this.audio.addEventListener('ended', (e) => {this.next();
            });this.dom.playbutton.addEventListener('click', this.toggle);this.dom.switchbutton.addEventListener('click', this.toggleList);if(!this.isMobile){this.dom.volumebutton.addEventListener('click', this.toggleMute);
            }this.dom.modebutton.addEventListener('click', this.switchMode);this.dom.musiclist.addEventListener('click', (e) => {
                let target,index,curIndex;if(e.target.tagName.toUpperCase() === 'LI'){
                    target = e.target;
                }else{
                    target = e.target.parentElement;
                }
                index = parseInt(target.getAttribute('data-index'));
                curIndex = parseInt(this.dom.musiclist.querySelector('.skPlayer-curMusic').getAttribute('data-index'));if(index === curIndex){this.play();
                }else{this.switchMusic(index + 1);
                }
            });this.dom.timeline_total.addEventListener('click', (event) => {
                let e = event || window.event;
                let percent = (e.clientX - Util.leftDistance(this.dom.timeline_total)) / this.dom.timeline_total.clientWidth;if(!isNaN(this.audio.duration)){this.dom.timeline_played.style.width = Util.percentFormat(percent);this.dom.timetext_played.innerHTML = Util.timeFormat(percent * this.audio.duration);this.audio.currentTime = percent * this.audio.duration;
                }
            });if(!this.isMobile){this.dom.volumeline_total.addEventListener('click', (event) => {
                    let e = event || window.event;
                    let percent = (e.clientX - Util.leftDistance(this.dom.volumeline_total)) / this.dom.volumeline_total.clientWidth;this.dom.volumeline_value.style.width = Util.percentFormat(percent);this.audio.volume = percent;if(this.audio.muted){this.toggleMute();
                    }
                });
            }
        }
    Copier après la connexion
    Voir le code

    至此,核心代码基本完成,接下来就是自己根据需要完成API部分。
    最后我们暴露模块:

    module.exports = skPlayer;
    Copier après la connexion

    一个HTML5音乐播放器就大功告成了 ~ !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal