技術的なポイント: ES6+Webpack+HTML5 Audio+Sass
ここでは、H5 音楽プレーヤーをゼロから実装する方法を段階的に学びます。
まず、最終的な実装を見てみましょう: デモリンク
それから本題に入りましょう:
音楽プレーヤーになるには、Web 上でオーディオが再生される方法をよく理解する必要があります、HTML5のaudioタグがよく使われます
audioタグについては、たくさんの属性、メソッド、イベントがありますので、ここで概要を説明します。
属性:
src: 必須、オーディオ ソース;
controls: 共通、設定後にブラウザのデフォルトのオーディオ コントロール パネルが表示され、設定されていない場合、オーディオ タグはデフォルトで非表示になります。設定後に自動的に再生されます (モバイル端末ではサポートされません) );
loop: 共通、設定後にオーディオがループで再生されます。
volume: レア、設定されます。または、オーディオ サイズを返します。値は 0 ~ 1 の浮動小数点数です (モバイル デバイスではサポートされていません)。
muted: レア、ミュート状態に戻ります。現在の再生時間を設定または返します。
paused: rare、一時停止するかどうか、現在の再生状態に戻ります。
buffered: rare、バッファリングされた期間情報、つまり読み込みの進行状況を含む TimeRanges オブジェクト。このオブジェクトには属性 length が含まれており、現在バッファリングされているオーディオ セグメントの数を示す 0 から始まる数値を返します。また、start と end の 2 つのメソッドも含まれており、それぞれパラメータ、つまり、どのセグメントを渡す必要があるかを示します。オーディオは0から読み込まれています。 start はセグメントの開始時間を返し、end はセグメントの終了時間を返します。例: 0 を渡します。最初の段落の開始は 0、終了時間は 17、単位は秒です。ここでは
属性が導入されていますが、playbackRate などのあまり使用されない属性がある可能性があります。動画再生時に使用する場合がありますので、説明は省略します。
メソッド:
play(): オーディオの再生を開始します;
pause(): オーディオの再生を一時停止します;
イベント:
canplay: 現在のオーディオの再生を開始できます (バッファーされたオーディオの一部のみがロードされます。すべてがロードされるわけではありません)。
canplaythrough : 一時停止せずに再生できます (つまり、すべてのオーディオがロードされます)。開始;
progress: オーディオのダウンロード イベントトリガープロセス中に、オーディオのバッファリングされた属性にアクセスすることで、読み込みの進行状況を取得できます。 : オーディオのジャンプが完了したとき、つまり currentTime が変更されたときにトリガーされます。
timeupdate: オーディオの再生中にトリガーされ、currentTime 属性が同期的に更新されます。
イベントはここで紹介されていますが、あまり使用されないイベントもあるかもしれません。まだ説明されるでしょう。
最後に、読み込みの開始から再生の終了までオーディオによってトリガーされるイベント フローと、さまざまな期間で操作できる属性について説明します。
loadstart: 読み込みの開始
durationchange: オーディオの継続時間を取得します。持続時間属性を取得します);
progress: オーディオのダウンロード (ダウンロード プロセスとともにトリガーされ、この時点でバッファー属性を取得できます);
canplay: 読み込まれたオーディオだけで再生を開始できます (これもトリガーされます)。一時停止後に再生を開始するたび);
canplaythrough: オーディオはすべてロードされます。
timeupdate: 再生中 (currentTime 属性は同期的に更新されます)。変更済み);
seeked: 現在の再生進行状況の変更が完了しました。
ended: 再生が完了しました。
これは、まれに使用される、リストされていないイベントがいくつかある場合があります。
イベントトリガープロセス中、オーディオのロードが開始される前に、コントロール、ループ、ボリュームなどのプロパティを設定できます。
全体の構造を決定します。プラグイン このメソッドは他の人が使用できるように npm で公開されているため、コードの記述にはオブジェクト指向のアプローチを使用します。ユーザーのニーズは異なるため、設計の開始時に多数の API と構成項目が公開されます。ほとんどのユーザーのニーズを満たします。
私は es6 の構文に慣れてきたので、開発効率を考慮して全体のプロセスを es6 に基づいて開発しました。最終的には webpack と webpack-dev- を使用しました。 es6 と sass をコンパイルするためのサーバー、プロジェクトのパッケージ化、ローカルサーバーの構築。
プレーヤーの UI とインタラクションを決定します:
インターフェースについては人それぞれの考えがあると思いますので、ここでは詳しく説明しません。例として私が作成したプレーヤー UI を分解してみましょう
。インターフェースからの一言 プレーヤーに必要な最も基本的な機能: 再生/一時停止、カバー/曲名/歌手表示、再生プログレスバー/ロードプログレスバー/プログレス操作機能、サイクルモード切り替え、プログレステキスト更新/曲の長さ、ミュート/音量サイズ制御、リスト表示ステータス制御、リスト項目をクリックして曲を切り替える
ユーザーのニーズを満たして構成項目と API を提供したいという出発点と組み合わせることで、構成項目と公開された API 項目を取得できます。デザインしたい内容:
設定項目:自動再生オンの有無、デフォルトソングリストの表示状態、デフォルトループモードの設定
API:再生/一時停止/切り替え、ループモード切替、ミュート/再開、リスト表示ステータス切り替え、前の曲/次の曲/切り替え曲 、現在のインスタンスを破棄します
webpack を使用するため、CSS を直接 js にパッケージ化して使用できるようにしますユーザー用のプラグインとして:
require('./skPlayer.scss');
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); } };
let instance = false;
class skPlayer { constructor(option){ } template(){ } init(){ } bind(){ } prev(){ } next(){ } switchMusic(index){ } play(){ } pause(){ } toggle(){ } toggleList(){ } toggleMute(){ } switchMode(){ } destroy(){ } }
if(instance){ console.error('SKPlayer只能存在一个实例!');return Object.create(null); }else{ instance = true; }
const defaultOption = { ... };this.option = Object.assign({},defaultOption,option);
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);
this.toggle = this.toggle.bind(this);this.toggleList = this.toggleList.bind(this);this.toggleMute = this.toggleMute.bind(this);this.switchMode = this.switchMode.bind(this);
this.root.innerHTML = this.template();
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'; }
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音乐播放器就大功告成了 ~ !
以上がHTML5 音楽プレーヤーの例を実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。