[刘阳Java]_酷炫视频播放器制作_JS篇

此文章是接着上次写的《酷炫视频播放器制作_界面篇》将其完善,我们主要给大家介绍一下如何利用JS脚本来控制视频的播放。为了让大家能够保持对要完成的功能有直接的了解,我们还是将效果图附到文章里面

完成本篇文章的代码编写,你能GET到200+代码量,且能够掌握很多有关video标签的属性,函数,事件的应用。当然希望大家也多多鼓励我写出更多更实际的文章来帮助大家学习的提升

第一步:我们先简单实现播放与暂停的效果,为了整个界面的DOM操作简单一点,我们就用jQuery来配合界面的操作

$(function() {
    var playVideo = $("video"); // 获取播放视频对象
    var playPause = $(".playPause"); // 获取播放与暂停
    var currentTime = $(".timebar .currentTime"); // 当前时间
    var duration = $(".timebar .duration"); // 总时间
    var progress = $(".timebar .progress-bar"); // 进度条
    var volumebar = $(".volumeBar .volumewrap").find(".progress-bar"); // 音量控制进度条
    playVideo[0].volume = 0.4; // 初始化音量
    
    // 播放按钮点击事件,目的控制视频播放与暂停
    playPause.on("click", function() {
        playControl();
    });
    // 屏幕点击事件,目的控制视频播放与暂定
    $(".playContent").on("click", function() {
        playControl();
    });
    
    /**
     * 控制播放的函数
     */
    function playControl() {
        // 切换播放按钮的样式        
        playPause.toggleClass('playIcon');
        if(playVideo[0].paused) {
            playVideo[0].play();
        } else {
            playVideo[0].pause();
        }
    }
});

 第二步:计算视频时长,时长的显示标准:小时:分钟:妙。这里我们会H5中video标签的duration属性,此属性返回视频的时长,时长计量单位秒

/**
 * 将视频时长转化为时间:小时,分钟,秒
 * @param {Object} value
 */
function formatSeconds(value) {
    value = parseInt(value);
    var time; // 存储转化好的时间格式
    if(value > -1) {
        hour = Math.floor(value / 3600); // 1小时=3600秒
        min = Math.floor(value / 60) % 60; // 1分钟=60秒 
        sec = value % 60;
        day = parseInt(hour / 24);
        if(day > 0) {
            hour = hour - 24 * day;
            time = day + "day " + hour + ":";
        } else {
            time = hour + ":";
        }
        if (min < 0) {
            time += "0"
        }
        time += min + ":";
        if (sec < 0) {
            time += "0";
        }
        time += sec;
    }
    return time;
}

 第三步:设置视频加载后将视频时长显示到页面上。这里会用到video标签的onloadedmetadata事件

/**
 * 视频加载结束后触发loadedmetadata事件
 * onloadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发
 * 视频/音频(audio/video)的元数据包含: 时长,尺寸大小(视频),文本轨道
 */
playVideo.on("loadedmetadata", function() {
    duration.text(formatSeconds(playVideo[0].duration));
});

 第四步:视频进度条更新,完成视频播放时候进度条不断加载播放进度。这里会用到video标签的timeupdate事件

/**
 * ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发
 * 该事件通常与 Video 对象的 currentTime 属性一起使用, 该属性返回视频/音频(audio/video)的当前播放位置
 */
playVideo.on("timeupdate", function() {
    currentTime.text(formatSeconds(playVideo[0].currentTime));
    progress.css("width", 100 * playVideo[0].currentTime / playVideo[0].duration + "%");
});

 第五步:视频播放完成需要完成的更新操作。这里会用到video标签的ended事件

/**
 * ended 事件在音频/视频(audio/video)播放完成后触发
 */
playVideo.on('ended', function() {
    playPause.toggleClass('playIcon');
});

 第六步:视频全屏播放,这里考虑兼容不同浏览器的内核(webkit,moz,ie)。同时还会用到video标签的requestFullscreen属性来判断全屏模式,document元素的exitFullScreen来退出全屏等功能设置

/**
 * 视频全屏播放
 * 这里尽量做到IE,Chrome,moz的内核的浏览器全屏播放的兼容性
 */
$('.fullScreen').on('click', function() {
    if ($(this).hasClass('cancleScreen')) {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.mozExitFullScreen) {
            document.mozExitFullScreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        }
        $(this).removeClass('cancleScreen');
        $('#willesPlay .playControll').css({
            'bottom': -48
        }).removeClass('fullControll');
    } else {
        if (playVideo[0].requestFullscreen) {
            playVideo[0].requestFullscreen();
        } else if (playVideo[0].mozRequestFullScreen) {
            playVideo[0].mozRequestFullScreen();
        } else if (playVideo[0].webkitRequestFullscreen) {
            playVideo[0].webkitRequestFullscreen();
        } else if (playVideo[0].msRequestFullscreen) {
            playVideo[0].msRequestFullscreen();
        }
        $(this).addClass('cancleScreen');
        $('#willesPlay .playControll').css({
            'left': 0,
            'bottom': 0
        }).addClass('fullControll');
    }
    return false;
});

 第七步:调整播放进度代码实现,思路如下

  • 通过offset().left获取进度条的坐标位置
  • 通过鼠标点击进度条坐标-进度条初始坐标位置=拉动进度条的偏移量(真实拉动距离)
  • 最后计算进度条的百分比,然后再转化为视频拉动的时间
/**
 * 拉动时间轴,调整播放的进度
 */
$(".timebar .progress").mousedown(function(e) {
    e = e || window.event;
    updatebar(e.pageX);
});
    
/**
 * 调整播放进度代码实现
 * 通过offset().left获取进度条的坐标位置
 * 通过鼠标点击进度条坐标-进度条初始坐标位置=拉动进度条的偏移量(真实拉动距离)
 * 最后计算进度条的百分比,然后再转化为视频拉动的时间
 */
var updatebar = function(x) {
    var maxduration = playVideo[0].duration; // 总时长
    var positions = x - progress.offset().left; // 拉动进度条的偏移量
    var percentage = 100 * positions / $(".timebar .progress").width();
    if(percentage > 100) {
        percentage = 100;
    }
    if (percentage < 0) {
        percentage = 0;
    }
    progress.css("width", percentage + "%");
    playVideo[0].currentTime = maxduration * percentage / 100;
}

 第八步:音量调整与控制

/**
 * 音量控制弹出窗
 */
$(".volume").on("click", function(e) {
    e = e || window.event;
    $(".volumeBar").toggle();
    e.stopPropagation();
});
    
/**
 * 音量控制事件监听
 * 多事件绑定:点击,鼠标滚轮等等方式来操作音量控制
 */
$(".volumeBar").on('click mousewhell DOMMouseScroll', function(e){
    e = e || window.event;
    volumeControl(e); // 控制音量调整的核心代码
    e.stopPropagation();
    return false;
});
    
/**
 * 控制音量调整的核心代码
 * @param {Object} e
 */
function volumeControl(e) {
    e = e || window.event;
    var eventype = e.type;
    var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) || (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1));
    var positions = 0;
    var percentage = 0;
    if (eventype == "click") {
        positions = volumebar.offset().top - e.pageY;
        percentage = 100 * (positions + volumebar.height()) / $('.volumeBar .volumewrap').height();
    } else if (eventype == "mousewheel" || eventype == "DOMMouseScroll") {
        percentage = 100 * (volumebar.height() + delta) / $('.volumeBar .volumewrap').height();
    }
    if (percentage < 0) {
        percentage = 0;
        $('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-off');
    }
    if (percentage > 50) {
        $('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-up');
    }
    if (percentage > 0 && percentage <= 50) {
        $('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-down');
    }
    if (percentage >= 100) {
        percentage = 100;
    }
    $('.volumewrap .progress-bar').css('height', percentage + '%');
    playVideo[0].volume = percentage / 100;
    e.stopPropagation();
    e.preventDefault();
}

最后还是温馨给出完整代码,供大家分享与预览,甚至拷贝都可以哈,杠杠得。。。

$(function() {
    var playVideo = $("video"); // 获取播放视频对象
    var playPause = $(".playPause"); // 获取播放与暂停
    var currentTime = $(".timebar .currentTime"); // 当前时间
    var duration = $(".timebar .duration"); // 总时间
    var progress = $(".timebar .progress-bar"); // 进度条
    var volumebar = $(".volumeBar .volumewrap").find(".progress-bar"); // 音量控制进度条
    playVideo[0].volume = 0.4; // 初始化音量
    
    // 播放按钮点击事件,目的控制视频播放与暂停
    playPause.on("click", function() {
        playControl();
    });
    // 屏幕点击事件,目的控制视频播放与暂定
    $(".playContent").on("click", function() {
        playControl();
        formatSeconds(playVideo[0].duration);
    });
    
    /**
     * 控制播放的函数
     */
    function playControl() {
        // 切换播放按钮的样式        
        playPause.toggleClass('playIcon');
        if(playVideo[0].paused) {
            playVideo[0].play();
        } else {
            playVideo[0].pause();
        }
    }
    
    /**
     * 点击网页任何地方让音量调节窗口关闭
     */
    $(document).click(function() {
        $(".volumeBar").hide();
    });
    
    /**
     * 视频加载结束后触发loadedmetadata事件
     * onloadedmetadata 事件在指定视频/音频(audio/video)的元数据加载后触发
     * 视频/音频(audio/video)的元数据包含: 时长,尺寸大小(视频),文本轨道
     */
    playVideo.on("loadedmetadata", function() {
        duration.text(formatSeconds(playVideo[0].duration));
    });
    
    /**
     * ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发
     * 该事件通常与 Video 对象的 currentTime 属性一起使用, 该属性返回视频/音频(audio/video)的当前播放位置
     */
    playVideo.on("timeupdate", function() {
        currentTime.text(formatSeconds(playVideo[0].currentTime));
        progress.css("width", 100 * playVideo[0].currentTime / playVideo[0].duration + "%");
    });
    
    /**
     * ended 事件在音频/视频(audio/video)播放完成后触发
     */
    playVideo.on('ended', function() {
        playPause.toggleClass('playIcon');
    });
    
    /**
     * 视频全屏播放
     * 这里尽量做到IE,Chrome,moz的内核的浏览器全屏播放的兼容性
     */
    $('.fullScreen').on('click', function() {
        if ($(this).hasClass('cancleScreen')) {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.mozExitFullScreen) {
                document.mozExitFullScreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            }
            $(this).removeClass('cancleScreen');
            $('#willesPlay .playControll').css({
                'bottom': -48
            }).removeClass('fullControll');
        } else {
            if (playVideo[0].requestFullscreen) {
                playVideo[0].requestFullscreen();
            } else if (playVideo[0].mozRequestFullScreen) {
                playVideo[0].mozRequestFullScreen();
            } else if (playVideo[0].webkitRequestFullscreen) {
                playVideo[0].webkitRequestFullscreen();
            } else if (playVideo[0].msRequestFullscreen) {
                playVideo[0].msRequestFullscreen();
            }
            $(this).addClass('cancleScreen');
            $('#willesPlay .playControll').css({
                'left': 0,
                'bottom': 0
            }).addClass('fullControll');
        }
        return false;
    });
    
    /**
     * 拉动时间轴,调整播放的进度
     */
    $(".timebar .progress").mousedown(function(e) {
        e = e || window.event;
        updatebar(e.pageX);
    });
    
    /**
     * 调整播放进度代码实现
     * 通过offset().left获取进度条的坐标位置
     * 通过鼠标点击进度条坐标-进度条初始坐标位置=拉动进度条的偏移量(真实拉动距离)
     * 最后计算进度条的百分比,然后再转化为视频拉动的时间
     */
    var updatebar = function(x) {
        var maxduration = playVideo[0].duration; // 总时长
        var positions = x - progress.offset().left; // 拉动进度条的偏移量
        var percentage = 100 * positions / $(".timebar .progress").width();
        if(percentage > 100) {
            percentage = 100;
        }
        if (percentage < 0) {
            percentage = 0;
        }
        progress.css("width", percentage + "%");
        playVideo[0].currentTime = maxduration * percentage / 100;
    }
    
    /**
     * 音量控制弹出窗
     */
    $(".volume").on("click", function(e) {
        e = e || window.event;
        $(".volumeBar").toggle();
        e.stopPropagation();
    });
    
    /**
     * 音量控制事件监听
     * 多事件绑定:点击,鼠标滚轮等等方式来操作音量控制
     */
    $(".volumeBar").on('click mousewhell DOMMouseScroll', function(e){
        e = e || window.event;
        volumeControl(e); // 控制音量调整的核心代码
        e.stopPropagation();
        return false;
    });
    
    /**
     * 控制音量调整的核心代码
     * @param {Object} e
     */
    function volumeControl(e) {
        e = e || window.event;
        var eventype = e.type;
        var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? 1 : -1)) || (e.originalEvent.detail && (e.originalEvent.detail > 0 ? -1 : 1));
        var positions = 0;
        var percentage = 0;
        if (eventype == "click") {
            positions = volumebar.offset().top - e.pageY;
            percentage = 100 * (positions + volumebar.height()) / $('.volumeBar .volumewrap').height();
        } else if (eventype == "mousewheel" || eventype == "DOMMouseScroll") {
            percentage = 100 * (volumebar.height() + delta) / $('.volumeBar .volumewrap').height();
        }
        if (percentage < 0) {
            percentage = 0;
            $('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-off');
        }
        if (percentage > 50) {
            $('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-up');
        }
        if (percentage > 0 && percentage <= 50) {
            $('.otherControl .volume').attr('class', 'volume glyphicon glyphicon-volume-down');
        }
        if (percentage >= 100) {
            percentage = 100;
        }
        $('.volumewrap .progress-bar').css('height', percentage + '%');
        playVideo[0].volume = percentage / 100;
        e.stopPropagation();
        e.preventDefault();
    }
});

/**
 * 将视频时长转化为时间:小时,分钟,秒
 * @param {Object} value
 */
function formatSeconds(value) {
    value = parseInt(value);
    var time; // 存储转化好的时间格式
    if(value > -1) {
        hour = Math.floor(value / 3600); // 1小时=3600秒
        min = Math.floor(value / 60) % 60; // 1分钟=60秒 
        sec = value % 60;
        day = parseInt(hour / 24);
        if(day > 0) {
            hour = hour - 24 * day;
            time = day + "day " + hour + ":";
        } else {
            time = hour + ":";
        }
        if (min < 0) {
            time += "0"
        }
        time += min + ":";
        if (sec < 0) {
            time += "0";
        }
        time += sec;
    }
    return time;
}

 

posted @ 2018-04-10 09:31  子墨老师  阅读(423)  评论(0编辑  收藏  举报