Technische Punkte: ES6+Webpack+HTML5 Audio+Sass
Hier erfahren wir Schritt für Schritt, wie man einen H5-Musikplayer von Grund auf implementiert.
Schauen wir uns zunächst die endgültige Implementierung an: Demo-Link
Dann kommen wir zur Sache:
Um einen Musikplayer für Sie zu erstellen Ich bin mit der Art und Weise, wie Audio im Web abgespielt wird, sehr vertraut. In Bezug auf das Audio-Tag gibt es eine große Anzahl von Attributen, Methoden und Ereignissen Einführung.
Attribute:
src: erforderlich, Audioquelle
Steuerelemente: allgemein, das Standard-Audio-Bedienfeld des Browsers wird nach der Einstellung angezeigt und das Audio-Tag wird standardmäßig ausgeblendet, wenn es nicht festgelegt ist;
Autoplay: üblich, Audio nach der Einstellung automatisch abspielen (wird vom Mobilgerät nicht unterstützt);
Loop: üblich, Audio wird nach der Einstellung in Schleife abgespielt;
Preload: üblich, Audio-Vorladung einstellen (wird vom Mobilgerät nicht unterstützt). Terminal);
Lautstärke: selten, legt die Audiogröße fest oder gibt sie zurück, der Wert ist eine Gleitkommazahl zwischen 0 und 1 (wird von mobilen Endgeräten nicht unterstützt);
stummgeschaltet: selten, legt den Stummschaltungsstatus fest oder gibt ihn zurück;
Dauer: selten, gibt die Audiodauer zurück;
aktuelle Zeit: legt die aktuelle Wiedergabezeit fest oder gibt sie zurück;
Pause: selten, gibt den aktuellen Wiedergabestatus zurück, ob pausiert werden soll; , ein TimeRanges-Objekt, das gepufferte Informationen über den Zeitraum enthält, d. h. den Ladefortschritt. Dieses Objekt enthält eine Attributlänge, die eine Zahl beginnend bei 0 zurückgibt, um anzugeben, wie viele Audiosegmente derzeit gepuffert sind. Außerdem enthält es zwei Methoden, start und end, die jeweils einen Parameter übergeben müssen, d. h. welches Segment des Audio wurde geladen. Beginnen Sie bei 0. start gibt die Startzeit des Segments zurück und end gibt die Endzeit des Segments zurück. Beispiel: Übergeben Sie 0, der Anfang des ersten Absatzes ist 0, die Endzeit ist 17, die Einheit ist Sekunden; hier wird das Attribut
eingeführt. Möglicherweise gibt es einige weniger häufig verwendete Attribute wie: Wiedergaberate usw ., während der Videowiedergabe Es kann verwendet werden, aber ich werde es noch nicht erklären.
Methoden:
play(): Audiowiedergabe starten;
pause(): Audiowiedergabe anhalten;
Ereignis:
canplay: Die aktuelle Audiowiedergabe kann beginnen ( nur ein Teil des gepufferten Teils wird geladen, aber nicht alles wird geladen); Wiedergabe endet;
Fehler: Es ist ein Fehler aufgetreten;
Wiedergabe: Wiedergabe wird gestartet; der Ladevorgang wird ausgelöst kann durch Zugriff auf das gepufferte Attribut von Audio abgerufen werden;
wird ausgelöst, wenn der Audiosprung geändert wird 🎜>timeupdate: Wird während der Audiowiedergabe ausgelöst und das Attribut currentTime wird synchron aktualisiert. Es kann sein, dass es einige weniger häufig verwendete Ereignisse gibt, die wir noch nicht erklären.
Abschließend erklären wir den Ereignisfluss, der durch ein Audio vom Beginn des Ladens bis zum Ende der Wiedergabe ausgelöst wird, sowie die Attribute, die wir in verschiedenen Zeiträumen bearbeiten können:
loadstart: Start des Ladens
Daueränderung: Erhalten Sie die Audiodauer (das Dauerattribut kann zu diesem Zeitpunkt abgerufen werden);
Fortschritt: Audio-Download (wird zusammen mit dem Downloadvorgang ausgelöst und das gepufferte Attribut kann zu diesem Zeitpunkt abgerufen werden); 🎜>canplay: Das geladene Audio reicht aus, um die Wiedergabe zu starten (Die Wiedergabe wird auch nach jeder Pause ausgelöst);
canplaythrough: alle Audios werden geladen
timeupdate: während der Wiedergabe (das currentTime-Attribut wird synchron aktualisiert);
suchend: Der aktuelle Wiedergabefortschritt wird geändert (d. h. (Um das currentTime-Attribut zu ändern);
suchend: Die Änderung des aktuellen Wiedergabefortschritts ist abgeschlossen;
beendet: Die Wiedergabe ist abgeschlossen;
Dies ist Der allgemeine Ereignisfluss des gesamten Audiomaterials. Möglicherweise gibt es einige weniger verwendete Ereignisse, die nicht aufgeführt sind.
Während des Ereignisauslösungsprozesses können einige Eigenschaften festgelegt werden, bevor das Audio geladen wird, wie zum Beispiel: Steuerung, Schleife, Lautstärke usw.;
Bestimmen Sie die Gesamtstruktur:
Da wir es als Plug-in erstellen und auf npm veröffentlichen, damit andere es verwenden können, verwenden wir einen objektorientierten Ansatz zum Schreiben von Code, und da Benutzer unterschiedliche Anforderungen haben, entwerfen wir Eine große Anzahl von APIs und Konfigurationselementen wird von Anfang an bereitgestellt, um den Anforderungen der meisten Benutzer gerecht zu werden.
Da ich mit der Syntax von es6 besser vertraut bin, habe ich den gesamten Prozess auf Basis von es6 entwickelt. Gleichzeitig habe ich aus Gründen der Entwicklungseffizienz Sass zum Schreiben von CSS verwendet. Dev-Server zum Kompilieren von ES6 und Sass, Projektpaketierung, Erstellen eines lokalen Servers.
Bestimmen Sie die Spieler-Benutzeroberfläche und die Interaktion:
Vielleicht hat jeder seine eigenen Vorstellungen von der Benutzeroberfläche, deshalb werde ich hier nicht auf Details eingehen. Nehmen wir die Spieler-Benutzeroberfläche, die ich erstellt habe, als Beispiel Aufschlüsseln
Auf der Benutzeroberfläche können Sie die grundlegendsten Funktionen sehen, die ein Player benötigt:
Wiedergabe/Pause, Cover-/Songtitel-/Sängeranzeige, Wiedergabe-Fortschrittsbalken/Lade-Fortschrittsbalken /progress-Betriebsfunktion, Schleifenmodusumschaltung, Fortschrittstextaktualisierung/Lieddauer, Stumm-/Lautstärkeregelung, Steuerung des Listenanzeigestatus, Klicken auf Listenelement zum Wechseln von Liedern
Kombiniert mit dem Ausgangspunkt der Bereitstellung von Konfigurationselementen und APIs, die wir wollen Um den Benutzeranforderungen gerecht zu werden, können wir herausfinden, welche Konfigurationselemente und offengelegten API-Elemente wir entwerfen möchten:
Konfigurationselemente: ob die automatische Wiedergabe aktiviert ist, der Anzeigestatus der Standard-Songliste und die Einstellungen der Standard-Loop-Modus
API: Wiedergabe/Pause/Umschalten, Loop-Modus Umschalten, Stummschalten/Wiederherstellen, Listenanzeigestatus wechseln, vorheriges Lied/nächstes Lied/Lied wechseln, aktuelle Instanz zerstören
Projektstruktur festlegen, mit dem Codieren beginnen:
Da wir Webpack verwenden, packen wir das CSS direkt in JS, sodass es als Plug-In für Benutzer verwendet werden kann:
require('./skPlayer.scss');
Öffentliche Methoden extrahieren. Es gibt viele öffentliche Methoden im Player, die möglicherweise extrahiert werden müssen, z. B.: Wenn Sie auf den Wiedergabe-Fortschrittsbalken und den Lautstärke-Fortschrittsbalken klicken, müssen Sie darauf klicken um den Abstand zwischen der Maus und dem linken Ende des Fortschrittsbalkens für den Fortschrittssprung zu berechnen. Die Zeit wird aus der Dauer in Sekunden usw. berechnet:
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 ? ('0' + tempMin) : tempMin; let curSec = tempSec < 10 ? ('0' + tempSec) : tempSec;return curMin + ':' + 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('GET',option.url); xhr.send(null); } };
Aufgrund des anfänglichen Designs ist unter Berücksichtigung der Einzigartigkeit des Players so konzipiert, dass nur eine Instanz existieren kann, und Es wird eine globale Variable festgelegt, um zu bestimmen, ob die Instanz derzeit vorhanden ist:
let instance = false;
Bei der Verwendung von ES6 fügen wir die Hauptlogik in den Konstruktor ein und fügen das äußerst vielseitige und ein API innerhalb der öffentlichen Funktion:
class skPlayer { constructor(option){ } template(){ } init(){ } bind(){ } prev(){ } next(){ } switchMusic(index){ } play(){ } pause(){ } toggle(){ } toggleList(){ } toggleMute(){ } switchMode(){ } destroy(){ } }
Instanzbeurteilung, wenn ein leeres Objekt vorhanden ist Ohne Prototyp wird ein leeres Objekt ohne Prototyp zurückgegeben, da der ES6-Konstruktor standardmäßig eine Instanz mit einem Prototyp zurückgibt:
if(instance){ console.error('SKPlayer只能存在一个实例!');return Object.create(null); }else{ instance = true; }
Initialisierungskonfigurationselemente , die Standardkonfiguration wird zusammengeführt mit der Benutzerkonfiguration:
const defaultOption = { ... };this.option = Object.assign({},defaultOption,option);
Gemeinsame Eigenschaften an die Instanz binden:
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);
Einige öffentliche Der interne Punkt von Die API verweist standardmäßig auf die Instanz, aber um die Menge an Code zu reduzieren, wird eine Reihe von Codes verwendet, um die Funktionen auf der Operationsschnittstelle und der API aufzurufen. Beim Binden von Ereignissen ändert sich dieser Punkt, also binden Sie diesen durch bind. Natürlich können Sie beim Binden von Ereignissen auch Pfeilfunktionen verwenden:
this.toggle = this.toggle.bind(this);this.toggleList = this.toggleList.bind(this);this.toggleMute = this.toggleMute.bind(this);this.switchMode = this.switchMode.bind(this);
Als nächstes verwenden wir die ES6-String-Vorlage, um mit der HTML-Generierung zu beginnen und sie in die Seite einzufügen:
this.root.innerHTML = this.template();
Als nächstes wird initialisiert. Während des Initialisierungsprozesses werden gemeinsame DOM-Knoten gebunden, Konfigurationselemente werden initialisiert und die Betriebsschnittstelle wird initialisiert:
this.init();
init(){this.dom = { cover: this.root.querySelector('.skPlayer-cover'), playbutton: this.root.querySelector('.skPlayer-play-btn'), name: this.root.querySelector('.skPlayer-name'), author: this.root.querySelector('.skPlayer-author'), timeline_total: this.root.querySelector('.skPlayer-percent'), timeline_loaded: this.root.querySelector('.skPlayer-line-loading'), timeline_played: this.root.querySelector('.skPlayer-percent .skPlayer-line'), timetext_total: this.root.querySelector('.skPlayer-total'), timetext_played: this.root.querySelector('.skPlayer-cur'), volumebutton: this.root.querySelector('.skPlayer-icon'), volumeline_total: this.root.querySelector('.skPlayer-volume .skPlayer-percent'), volumeline_value: this.root.querySelector('.skPlayer-volume .skPlayer-line'), switchbutton: this.root.querySelector('.skPlayer-list-switch'), modebutton: this.root.querySelector('.skPlayer-mode'), musiclist: this.root.querySelector('.skPlayer-list'), musicitem: this.root.querySelectorAll('.skPlayer-list li') };this.audio = this.root.querySelector('.skPlayer-source');if(this.option.listshow){this.root.className = 'skPlayer-list-on'; }if(this.option.mode === 'singleloop'){this.audio.loop = true; }this.dom.musicitem[0].className = 'skPlayer-curMusic'; }
Ereignisbindung, hauptsächlich Bindung von Audioereignissen und Bedienfeldereignissen :
this.bind();
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(); } }); } }
至此,核心代码基本完成,接下来就是自己根据需要完成API部分。
最后我们暴露模块:
module.exports = skPlayer;
一个HTML5音乐播放器就大功告成了 ~ !
Das obige ist der detaillierte Inhalt vonImplementieren Sie ein Beispiel für einen HTML5-Musikplayer. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!