百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>html5教程> 实现一个HTML5音乐播放器的实例-
分享文章到:

实现一个HTML5音乐播放器的实例-

发布时间:08/01 来源:未知 浏览: 关键词:
技术点:ES6+Webpack+HTML5Audio+Sass这里,我们将一步步的学到怎样从零去实现一个H5音乐播放器。第一来看一下终究的实现结果:Demo链接?接下来就步入正题:要做一个音乐播放器就要非常理解在Web中音频播放的方式,平常都采纳HTML5的audio标签对于audio标签,它有批量的属性、办法和事件,在这里我就做一个大致的介绍。属性:src:必须,音频来源 技术点:ES6+Webpack+HTML5 Audio+Sass

这里,我们将一步步的学到怎样从零去实现一个H5音乐播放器。

第一来看一下终究的实现结果:Demo链接

接下来就步入正题:

  1. 要做一个音乐播放器就要非常理解在Web中音频播放的方式,平常都采纳HTML5的audio标签
    对于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为例进行分解

    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音乐播放器的实例的细致内容,更多请关注 百分百源码网 其它相干文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有151人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板