备注:因为懒得去重复些一堆的事件兼容性函数,先用jQuery库快速捣鼓一个audio音频组件。等以后有空了,再干掉jQuery库的依赖,用纯JavaScript重构一下。

这个组件包含进度条拖拽,支持自定制audio的样式。体验如下:

直接上代码:

组件代码:

/*
* 音频组件
* options参数:
*     @param src {String}  # 音频资源
      @param autoplay {Boolean}  # 是否自动播放。默认值为false
      @param loop {Boolean}  # 是否循环播放。默认值为true
      @param btnPlay {String}  # 播放按钮DOM的query
      @param btnPause {String}  # 暂停按钮DOM的query
      @param slideBar {String}  # 可滑动进度条DOM的query
      @param slideThumb {String}  # 可滑动进度条的控制按钮DOM的query
      @param playing {Function(curTime, duration)}  # 音频正在播放时触发的回调函数,参数分别有当前播放时间、总播放时间
      @param ended {Function} # 音频播放结束时的回调函数
      @param seeked {Function} # 音频TimeRange加载完成的回调函数
* 创建实例的方法:
      var mp3 = audioComponent.create(options);
* 实例方法:
      @method play  # 继续播放音频,回调函数的参数是当前播放时间
      @method pause  # 暂停音频,回调函数的参数是当前播放时间
      @method playPause  # 切换视频播放,回调函数的参数是当前播放时间、是否已经暂停
      @method getDuration  # 获取音频的总播放时间(ms)
      @method getCurrentTime  # 获取音频当前播放时间(ms)
      @method onPlaying  # 监听音频播放的回调函数,参数分别有当前播放时间、总播放时间
 */
function audioComponent(options) {
    // 默认参数设置
    this.src = options.src || "";
    this.autoplay = options.autoplay || false;
    this.loop = options.loop || true;
    this.btnPlay = options.btnPlay || "";
    this.btnPause = options.btnPause || "";
    this.slideBar = options.slideBar || "";
    this.slideThumb = options.slideThumb || "";
    this.playing = options.playing || null;
    this.ended = options.ended || null;
    this.seeked = options.seeked || null;

    this.duration = 0;
    this.currentTime = 0;
    this.isSlideMouseMove = false;
};
audioComponent.prototype = {
    // 创建audio元素
    _create: function() {
        var _this = this;
        var audio = $("<audio>").attr(
            {
                "src": _this.src,
                "autoplay": _this.autoplay,
                "loop": _this.loop
            });
        $("body").append(audio);
        _this.audio = audio[0];
    },
    // 获取音频播放的总时长
    _seeked: function() {
        var _this = this;
        $(_this.audio).on('seeked progress', function() {
            _this.duration = _this.audio.seekable.end(0);
            if(typeof _this.seeked == "function") {
                _this.seeked(_this.duration);
            }
        });
    },
    // 播放
    play: function(callback) {
        var audio = this.audio;
        audio.play();
        if(typeof callback == "function") {
            callback(audio.currentTime);
        }
    },
    // 暂停
    pause: function(callback) {
        var audio = this.audio;
        audio.pause();
        if(typeof callback == "function") {
            callback(audio.currentTime);
        }
    },
    // 播放与暂停切换
    playPause: function(callback) {
        var audio = this.audio;
        var isPause = audio.paused;
        if(isPause) {
            this.play();
        } else {
            this.pause();
        }
        if(typeof callback == "function") {
            callback(audio.currentTime, isPause);
        }
    },
    // 获取音频总播放时间
    getDuration: function() {
        return this.duration;
    },
    // 获取音频当前播放时间
    getCurrentTime: function() {
        return this.currentTime;
    },
    // 音频正在播放的回调函数
    onPlaying: function(callback) {
        var _this = this,
            audio = this.audio;
        this.currentTime = audio.currentTime;
        if(audio.addEventListener) {
            audio.addEventListener("timeupdate", function() {
                if(typeof callback == "function") {
                    callback(audio.currentTime);
                }
                if(typeof _this.playing == "function") {
                    _this.playing(audio.currentTime);
                }
            });
        }
    },
    // 按钮的事件绑定
    _domBind: function() {
        var _this = this;
        if(this.btnPlay) {
            $(document).on("click", this.btnPlay, function() {
                _this.play();
            });
        }
        if(this.btnPause) {
            $(document).on("click", this.btnPause, function() {
                _this.pause();
            });
        }
    },
    // 滑动条事件绑定
    _slideBind: function() {
        var _this = this,
            slideBar = $(this.slideBar),
            slideThumb = $(this.slideThumb),
            audio = this.audio;
        var totalWidth = slideBar.width();
        // 按钮跟随音乐播放
        _this.onPlaying(function(curTime) {
            if(!_this.isSlideMouseMove) {
                var duration = _this.duration;
                ratio = totalWidth / duration;
                slideThumb.css("left", curTime * ratio);
            }
        });
        // 滑块滑动事件绑定
        var isMousedown = false,
            initConfig = {
                time: 0
            },
            moveConfig = {};
        $(document).on("mousedown", this.slideThumb, function(e) {
            isMousedown = true;
            initConfig.time = audio.currentTime;
            initConfig.x = e.pageX;
            initConfig.left = parseInt($(this).css("left"));
            _this.isSlideMouseMove = true;
        })
        .on("mousemove", this.slideThumb, function(e) {
            if(isMousedown) {
                e.preventDefault();
                moveConfig.x = e.pageX;
                var deltaX = moveConfig.x - initConfig.x;
                var slideLeft = initConfig.left + deltaX;
                if(slideLeft >= totalWidth) {
                    slideLeft = totalWidth;
                } else if(slideLeft <= 0) {
                    slideLeft = 0;
                }
                moveConfig.time = slideLeft * _this.duration / totalWidth;
                slideThumb.css("left", slideLeft);
            }
        })
        .on("mouseup", function(e) {
            if(isMousedown) {
                isMousedown = false;
                audio.currentTime = moveConfig.time;
                audio.play();

                moveConfig = {};
                initConfig = {};

                setTimeout(function() {
                    _this.isSlideMouseMove = false;
                }, 100);
            }
        });

        // 滑动条上的点击事件
        $(document).on("click", this.slideBar, function(e) {
            e.stopPropagation();
            var mouseX = e.pageX;
            var offsetLeft = $(this).offset().left;
            var slideLeft = mouseX - offsetLeft;
            var currentTime = slideLeft * _this.duration / totalWidth;
            slideThumb.css("left", slideLeft);
            audio.currentTime = currentTime;
            audio.play();
        });
    },
    init: function() {
        this._create();
        this._seeked();
        this._domBind();
        this._slideBind();
    }
};
audioComponent.create = function(options) {
    var audio = new audioComponent(options);
    audio.init();
    return audio;
};

组件的使用方法:

var $totalTimeText = $(".text-totalTime");
var $curTimeText = $(".text-curTime");

// 实例化一个音频实例
var mp3 = audioComponent.create({
    src: "danqingke.mp3",
    autoplay: false,
    loop: true,
    btnPlay: "#btn-play",
    btnPause: "#btn-pause",
    slideBar: ".slidebar",
    slideThumb: ".slide-thumb",
    seeked: function(duration) {
        var totalTimeText = timeFormat(duration);
        $totalTimeText.text(totalTimeText);
    },
    playing: function(curtime, duration) {
        var curTimeText = timeFormat(curtime);
        $curTimeText.text(curTimeText);
    },
});

// 时间格式化 mm:ss
function timeFormat(s) {
    var second = s % 60 > 0 ? parseInt(s % 60) : s;
    var minute = s / 60 > 0 ? parseInt(s / 60) : 0;
    second = second > 10 ? second : "0" + second;
    minute = minute > 10 ? minute : "0" + minute;
    return minute + ":" + second;
}

CSS代码:

.btn {
    display: inline-block;
    margin: 0 10px;
    padding: 5px 10px;
    font-size: 14px;
    color: #fff;
    border-radius: 5px;
    background: #4dbb89;
    cursor: pointer;
}
.time {
    margin: 10px 20px;
}
.slidebar {
    margin: 0 20px;
    position: relative;
    width: 150px;
    height: 8px;
    background: #969595;
    border-radius: 5px;
}
.slidebar .slide-thumb {
    position: absolute;
    display: inline-block;
    width: 18px;
    height: 18px;
    margin-left: -9px;
    margin-top: -5px;
    border-radius: 50%;
    background: #41bba0;
}

HTML代码:

<div class="btn" id="btn-play">play</div><div class="btn" id="btn-pause">pause</div>
<div class="time">
    <span class="text-curTime">00:00</span> / <span class="text-totalTime"></span>
</div>
<div class="slidebar"><span class="slide-thumb"></span></div>
本文作者:子匠_Zijor,转载请注明出处:http://www.dengzhr.com/frontend/html/1236