1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          skplayer(HTML5如何實現音樂播放器)

          來源:互聯網轉載 時間:2024-05-08 13:18:43

          要做一個音樂播放器就要非常了解在Web中音頻播放的方式,通常都采用HTML5的audio標簽

          1. 關于audio標簽,它有大量的屬性、方法和事件,在這里我就做一個大致的介紹。

            屬性:
            src:必需,音頻來源;
            controls:常見,設置后顯示瀏覽器默認的audio控制面板,不設置默認隱藏audio標簽;
            autoplay:常見,設置后自動播放音頻(移動端不支持);
            loop:常見,設置后音頻將循環播放;
            preload:常見,設置音頻預加載(移動端不支持);
            volume:少見,設置或返回音頻大小,值為0-1之間的一個浮點數(移動端不支持);
            muted:少見,設置或返回靜音狀態;
            duration:少見,返回音頻時長;
            currentTime:少見,設置或返回當前播放時間;
            paused:少見,返回當前播放狀態,是否暫停;
            buffered:少見,一個TimeRanges對象,包含已緩沖的時間段信息,即加載進度。該對象包含一個屬性length,返回一個從0開始的數表示當前緩沖了多少段音頻;還包含兩個方法,start、end,分別需要傳入一個參數,即傳入音頻已加載的第幾段,從0開始。start返回該段的起始時間,end返回該段的終點時間。舉例:即傳入0,第一段的起始是0,終止時間是17,單位秒;
            屬性就介紹到這里,可能還有一些比較少用的屬性如:playbackRate等,在視頻播放中可能會用到,我就暫不講解。

            方法:
            play():開始播放音頻;
            pause():暫停播放音頻;

            事件:
            canplay:當前音頻可以開始播放(只加載了部分buffered,并未全部加載完成);
            canplaythrough:可以無停頓播放(即音頻全部加載完成);
            durationchange:音頻時長發生變化;
            ended:播放結束;
            error:發生錯誤;
            pause:播放暫停;
            play:播放開始;
            progress:音頻下載過程中觸發,事件觸發過程中可以通過訪問audio的buffered屬性獲取加載進度;
            seeking:音頻跳躍中觸發,即為修改currentTime時;
            seeked:音頻跳躍完成時觸發,即為修改完成currentTime時;
            timeupdate:音頻播放過程中觸發,同時currentTime屬性在同步更新;
            事件就介紹到這里,可能還有一些不常用的事件暫不講解。

            最后再講解一下一個音頻從開始加載到播放結束過程中,所觸發的事件流以及我們在不同時間段可以操作的屬性:
            loadstart:開始加載;
            durationchange:獲取到音頻時長(此時可以獲取duration屬性);
            progress:音頻下載中(將伴隨下載過程一直觸發,此時可以獲取buffered屬性);
            canplay:所加載的音頻足夠開始播放(每次暫停后開始播放也會觸發);
            canplaythrough:音頻全部加載完成;
            timeupdate:播放過程中(currentTime屬性伴隨著同步更新);
            seeking:修改當前播放進度中(即為修改currentTime屬性);
            seeked:修改當前播放進度完成;
            ended:播放完成;
            這就是整個音頻的大致事件流,可能有一些少用的事件沒有列舉出。
            在事件觸發過程中,有一些屬性在音頻還沒有開始加載的時候就可以設置,如:controls、loop、volume等等;

          2. 確定整體結構:
            因為自己是做成插件的方式發布在npm上供他人使用的,所以我們就采用面向對象的方式進行代碼編寫,又因為用戶的需求不一,所以在設計之初就暴露出大量的API和配置項以滿足大部分用戶的需求。
            這里因為自己更習慣es6的語法,就全程以es6為基礎進行開發,同時為了開發效率,又使用了sass進行css的編寫,最后還使用了webpack和webpack-dev-server用以編譯es6和sass,項目打包,構建本地服務器。


          3. 確定播放器UI和交互:
            可能關于界面每個人有自己的想法,這里就不過多贅述了,以我做好的播放器UI為例進行分解

            從界面中可以看出一個播放器所需要的最基礎功能:
            播放/暫停、封面/歌名/歌手的顯示、播放進度條/加載進度條/進度操作功能、循環模式切換、進度文字更新/歌曲時長、靜音/音量大小控制、列表顯示狀態控制、點擊列表項切歌功能
            再結合我們想要滿足用戶需求,提供配置項和API的出發點可以得出我們想設計的配置項和暴露的API項:
            配置項:自動播放是否開啟、默認歌曲列表的顯示狀態、默認循環模式的設置
            API:播放/暫停/toggle、循環模式的切換、靜音/恢復、列表顯示狀態的切換、上一曲/下一曲/切歌、銷毀當前實例


          4. 確立項目結構,開始編碼:
            因為使用webpack,所以我們直接將css打包至js內,以便作為插件供用戶使用:

            require('./skPlayer.scss');

            抽離公共方法,在播放器中有很多可能需要抽離的公共方法如:點擊播放進度條和音量進度條時需要計算鼠標距離進度條左端的距離以進行進度跳轉,時間從duratin中獲取到的以秒為單位的時間轉換成標準時間格式等等:

            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);    }};
            View Code

            由于設計之初,考慮到播放器的獨特性,設計為只能存在一個實例,設置了一個全局變量以判斷當前是否存在實例:

            let instance = false;

            在使用ES6的情況下,我們將主邏輯放在構造函數內部,將通用性強和API放在公共函數內部:

            class skPlayer {    constructor(option){    }    template(){    }    init(){    }    bind(){    }    prev(){    }    next(){    }    switchMusic(index){    }    play(){    }    pause(){    }    toggle(){    }    toggleList(){    }    toggleMute(){    }    switchMode(){    }    destroy(){    }}
            View Code

            實例判斷,如果存在返回無原型的空對象,因為ES6構造函數內默認返回帶原型的實例:

                    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);

            一些公共的API內部this指向在默認情況下指向實例,但是為了減少代碼量,將操作界面上的功能與API調用一套代碼,在綁定事件的時候this指向會改變,所以通過bind的方式綁定this,當然也可以在綁定事件的時候使用箭頭函數:

                    this.toggle = this.toggle.bind(this);this.toggleList = this.toggleList.bind(this);this.toggleMute = this.toggleMute.bind(this);this.switchMode = this.switchMode.bind(this);

            接下來,我們就使用ES6字符串模板開始生成HTML,插入到頁面中:

                        this.root.innerHTML = this.template();

            接下來初始化,初始化過程中將常用DOM節點綁定,初始化配置項,初始化操作界面:

                        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';    }
            View Code

            事件綁定,主要綁定audio的事件以及操作面板的事件:

                        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();                }            });        }    }
            View Code

            至此,核心代碼基本完成,接下來就是自己根據需要完成API部分。
            最后我們暴露模塊:

            module.exports = skPlayer;

            一個HTML5音樂播放器就大功告成了 ~ !

          感謝你能夠認真閱讀完這篇文章,希望小編分享HTML5如何實現音樂播放器內容對大家有幫助,同時也希望大家多多支持本站,關注本站行業資訊頻道,遇到問題就找本站,詳細的解決方法等著你來學習!

          標簽:skplayer-

          c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...

          2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...

          :喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...

          美國最新CPI數據顯示,2021年11月CPI同比大漲6.8%,創1982年6月(39年)以來的最高水平??鄢称泛湍茉吹暮诵腃PI同比上漲4.9%,漲幅比10月的4.6%還要大,這也是1991年以來的最高漲幅。上月11日,美國CPI剛剛創下31年最高水平。機構認為:CPI同比讀數再度走高,創近40年來新高,但并未超海外市場預期。11月CPI同比繼續攀升至6.8%,是1982年6月以來的新高。但是...

          高轉送股票的定義是什么?高送轉股票(簡稱:高送轉)簡單理解為:股數增加,股價變小。舉例:1張100元,換成了2張50元,數量增加總價值沒變動。是指送紅股或者轉增股票的比例很大。實質是股東權益的內部結構調整,對凈資產收益率沒有影響,對公司的盈利能力也并沒有任何實質性影響。“高送轉”后,公司股本總數雖然擴大了,但公司的股東權益并不會因此而增加。而且,在凈利潤不變的情況下,由于股...

          (資料圖片)最近小編看到大家都在討論江蘇哪里是地震帶相關的事情,對此呢小編也是非常的感應興趣,那么這件事究竟是怎么發生的呢?具體又是怎么回事呢?下面就是小編搜索到的關于江蘇哪里是地震帶事件的相關信息,我們一起來看一下吧!大概位于山東臨沂到江蘇泗洪一帶。地震帶簡介:地震帶是指地震集中分布的地帶,地球上主要有三處地震帶。地震帶基本上在板塊交界處,在地震帶內震中密集,在帶外地震的分布零散。地震帶常與一定...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>