如何使用HTML设计自定义音频播放器

时间:2016-05-26 05:27:50

标签: javascript html css html5 html5-audio

我有一个音频播放器的布局,我想与HTML音频播放器元素一起使用。

enter image description here

我正在尝试<audio></audio>,并且它给了我默认播放器:

enter image description here

有没有办法改变播放器的样式以使用我想要使用的布局?

3 个答案:

答案 0 :(得分:6)

您可以非常快速地为HTML5音频播放器制作一套非常漂亮的自定义音频控件。使用(主要)基本的HTML和CSS,只需要一些简单的Javascript事件处理。该解决方案是基于所提供设计的全功能定制音频播放器。

完整的代码和示例可以在jsFiddle:https://jsfiddle.net/mgaskill/zo3ede1c/中找到。点击并随意播放,因为它确实是一个有效的音频播放器。

播放器

播放器包含原始设计中描述的所有元素。您可以在第一张图片中看到这一点(并与原始图片进行比较):

enter image description here

此外,我通过提供一个可折叠的信息托盘&#34;稍微扩展了设计,通过按下&#34;更多信息&#34;隐藏并显示右边的按钮。您可以在第二张图片中看到部署的托盘:

enter image description here

当然,颜色并不相同,并且可能存在与原始设计不同的像素差异,但它非常接近。我的核心技能不是CSS,所以那里有改进的余地。但是,它非常非常接近原始设计,并保留了该设计的所有精神,布局和功能。

工具

为方便起见,该解决方案使用了一些外部元素。这些是:

HTML

HTML采用将音频控件面板上的每个组件作为单独元素进行处理的方法。 HTML布局很漂亮,唯一有趣的部分就是使用FontAwesome类来实现播放/暂停和音量/静音按钮的初始状态图标。

<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<audio id="player">
    <source src="http://www.noiseaddicts.com/samples_1w72b820/2543.mp3" type="audio/mpeg" />
</audio>

<div id="audio-player">
    <div id="controls">
        <i id="play" class="fa fa-pause"></i>
        <span id="start-time" class="time">00:00</span>
        <div id="progressbar"></div>
        <span id="time" class="time">00:00</span>
        <i id="mute" class="fa fa-volume-up"></i>
        <div id="volume"></div>    
    </div>
    <div id="more-info-box">
        <span id="more-info">MORE INFO</span>
    </div>
    <div id="info-tray">
        Track: <span id="track">Semper Fidelis March</span>
    </div>
</div>

请注意,整个音频控件都包含在#audio-player元素中。

CSS

CSS赋予HTML生命,在这种情况下,用于提供颜色,位置和操作。

#audio-player {
    height: 50px;
    width: 500px;
    overflow: hidden;
    background-color: #2B2B2B;
    color: white;
    -webkit-user-select: none; /* webkit (safari, chrome) browsers */
    -moz-user-select: none;    /* mozilla browsers */
    -khtml-user-select: none;  /* webkit (konqueror) browsers */
    -ms-user-select: none;     /* IE10+ */
}

#controls {
    height: 50px;
    background-color: #808080;
    width: 350px;
}

.time {
    font-size: 10px;
    color: white;
    position: relative;
    top: 14px;
    margin: 5px;
}

.ui-progressbar {
    background: #2B2B2B;
}

.ui-progressbar-value {
    background: white;
}

#progressbar, #volume {
    height: 10px;
    display: inline-block;
    border-radius: 0px;
    border: none;
    position: relative;
    top: 16px;
}

#progressbar {
    width: 150px;
}

#play, #mute {
    font-size: 16px;
    width: 20px;
    position: relative;
    top: 17px;
}

#play {
    margin-left: 15px;
}

#volume {
    width: 50px;
}

#more-info-box {
    display: inline-block;
    width: 150px;
    height: 50px;
    position: relative;
    left: 350px;
    top: -50px;
    padding-top: 18px;
    text-align: center;
    font-family: sans-serif;
    font-size: 12px;
    color: white;
}

#more-info-box, #more-info-box > span {
    cursor: context-menu;
}

#info-tray {
    display: inline-block;
    color: white;
    position: relative;
    width: 100%;
    top: -65px;
    height: 50px;
    padding: 5px;
}

虽然大部分内容非常简单,但仍有一些有趣的事情发生。

首先,#audio-player样式调用特定于浏览器的(但不是全包)样式来禁用控件的文本选择:

-webkit-user-select: none; /* webkit (safari, chrome) browsers */
-moz-user-select: none;    /* mozilla browsers */
-khtml-user-select: none;  /* webkit (konqueror) browsers */
-ms-user-select: none;     /* IE10+ */

jQueryUI进度条控件使用预定义的类使用条形颜色设置样式:

.ui-progressbar {
    background: #2B2B2B;
}

.ui-progressbar-value {
    background: white;
}

div - 通过更改显示布局来正确布局:

display: inline-block;

使用相对定位将控件显式放置在适当的位置:

position: relative;

Javascript

Javascript主要面向处理各种控件和状态的事件。

var audio_player = $("#audio-player");
var play_button = $('#play');
var progress_bar = $("#progressbar");
var time = $("#time");
var mute_button = $('#mute');
var volume_bar = $('#volume');
var more_info = $('#more-info-box');
var info_tray = $("#info-tray");
var player = document.getElementById('player');
var duration = 0;
var volume = 0.75;

player.onloadedmetadata = function() {
    duration = player.duration;
    progress_bar.progressbar("option", { 'max' : duration });
};

player.load();
player.volume = 0.75;
player.addEventListener("timeupdate", function() {
    progress_bar.progressbar('value', player.currentTime);
    time.text(getTime(player.currentTime));
}, false);

function getTime(t) {
    var m=~~(t/60), s=~~(t % 60);
    return (m<10?"0"+m:m)+':'+(s<10?"0"+s:s);
}

function getProgressBarClickInfo(progress_bar, e) {
    var offset = progress_bar.position();
    var x = e.pageX - offset.left; // or e.offsetX (less support, though)
    var y = e.pageY - offset.top;  // or e.offsetY
    var max = progress_bar.progressbar("option", "max");
    var value = x * max / progress_bar.width();

    return { x: x, y: y, max: max, value: value };
}

volume_bar.progressbar({
    value : player.volume*100,
});

volume_bar.click(function(e) {
    var info = getProgressBarClickInfo($(this), e);
    volume_bar.progressbar('value', info.value);
    player.volume = info.value / info.max;
});

progress_bar.progressbar({
    value : player.currentTime,
});

progress_bar.click(function(e) {
    var info = getProgressBarClickInfo($(this), e);
    player.currentTime = player.duration / info.max * info.value;
});

play_button.click(function() {
    player[player.paused ? 'play' : 'pause']();
    $(this).toggleClass("fa-play", !player.paused);
    $(this).toggleClass("fa-pause", player.paused);
});

mute_button.click(function() {
    if (player.volume == 0) {
        player.volume = volume;
    } else {
        volume = player.volume;
        player.volume = 0;
    }

    volume_bar.progressbar('value', player.volume * 100);

    $(this).toggleClass("fa-volume-up", player.volume != 0);
    $(this).toggleClass("fa-volume-off", player.volume == 0);
});

more_info.click(function() {
    audio_player.animate({
        height: (audio_player.height() == 50) ? 100 : 50
    }, 1000);
});

onloadedmetadata事件处理程序用于识别音频加载的时间,以便可以将音轨进度初始化为音轨的长度(持续时间)。

timeupdate事件处理程序用于在播放音轨时更新曲目进度。这允许进度条向右增长以反映音轨中的当前位置。

使用jQueryUI进度条控件初始化volumeprogress_bar元素,并设置click个处理程序以允许用户单击以动态更改位置。

play_buttonmute_button处理点击以更改播放状态(播放/暂停)或音频状态(音量开/关)。这些处理程序动态交换相应的FontAwesome类,以正确反映按钮上的当前状态。

最后,more_info点击处理程序显示/隐藏信息托盘元素。隐藏/显示使用jQuery animate进行动画处理,以提供类似立体声组件的感觉,让人想起CD托盘弹出。此外,它为控制器提供了良好的伺服感觉。因为那是我想要它做的,而不是其他原因。

答案 1 :(得分:2)

据我所知,您无法设置默认播放器的样式,但您可以使用plyr.io等插件创建自定义播放器(基于audio标签),您可以编辑插件的风格如你所愿。

例如:

&#13;
&#13;
plyr.setup(document.querySelectorAll('.js-plyr'), {});
&#13;
<link rel="stylesheet" href="https://cdn.plyr.io/1.6.16/plyr.css">
<script src="https://cdn.plyr.io/1.6.16/plyr.js"></script>

<div class="js-plyr">
  <audio controls="" crossorigin="">
    <source src="https://cdn.selz.com/plyr/1.5/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3" type="audio/mp3">
    <source src="https://cdn.selz.com/plyr/1.5/Kishi_Bashi_-_It_All_Began_With_a_Burst.ogg" type="audio/ogg" />
  </audio>
</div>
&#13;
&#13;
&#13;

http://jsbin.com/zajeji/edit?html,js,output

答案 2 :(得分:0)

Michael Gaskill,您的回答很好,我在项目中使用了它,对我有很大帮助。但是我在尝试单击进度或音量时遇到了一些JS问题,因此我几乎没有修改JS代码。如果有人也遇到JS问题,请使用此问题。希望对您有所帮助。

https://jsfiddle.net/xohcw6u7/1/

$(document).ready(function() {
        var audio_player = $("#audio-player");
    var play_button = $('#play');
    var progress_bar = $("#progressbar");
    var time = $("#time");
    var mute_button = $('#mute');
    var volume_bar = $('#volume');
    var more_info = $('#more-info-box');
    var player = $('#player')[0];
    var duration = 0;
    var volume = 0.5;
    var end_time = $('#end-time');
    player.onloadedmetadata = function () {
            duration = player.duration;
        var minutes = parseInt(duration / 60, 10);
        var seconds = parseInt(duration % 60);
        // finding and appending full duration of audio
        end_time.text(minutes + ':' + seconds);
        console.log('ddd', progress_bar)
        progress_bar.progressbar("option", { 'max': duration });
    };
    player.load();
    player.volume = 0.5;
    player.addEventListener("timeupdate", function () {
        progress_bar.progressbar('value', player.currentTime);
        time.text(getTime(player.currentTime));
    }, false);
    volume_bar.progressbar({
        value: player.volume * 100,
    });

    volume_bar.click(function (e) {
        var info = getProgressBarClickInfo($(this), e);
        volume_bar.progressbar('value', info.value);
        player.volume = info.value / info.max;
    });

    progress_bar.progressbar({
        value: player.currentTime,
    });

    progress_bar.click(function (e) {
        var info = getProgressBarClickInfo($(this), e);
        player.currentTime = player.duration / info.max * info.value;
    });

    play_button.click(function () {
        player[player.paused ? 'play' : 'pause']();
        $(this).toggleClass("fa-play", player.paused);
        $(this).toggleClass("fa-pause", !player.paused);
    });

    mute_button.click(function () {
        if (player.volume == 0) {
            player.volume = volume;
        } else {
            volume = player.volume;
            player.volume = 0;
        }

        volume_bar.progressbar('value', player.volume * 100);

        $(this).toggleClass("fa-volume-up", player.volume != 0);
        $(this).toggleClass("fa-volume-off", player.volume == 0);
    });

    more_info.click(function () {
        audio_player.animate({
          height: (audio_player.height() == 50) ? 100 : 50
        }, 1000);
    });
});
function getTime(t) {
    var m = ~~(t / 60), s = ~~(t % 60);
    return (m < 10 ? "0" + m : m) + ':' + (s < 10 ? "0" + s : s);
}

function getProgressBarClickInfo(progress_bar, e) {
    var offset = progress_bar.offset();
    var x = e.pageX - offset.left; // or e.offsetX (less support, though)
    var y = e.pageY - offset.top;  // or e.offsetY
    var max = progress_bar.progressbar("option", "max");
    var value = (x * max) / progress_bar.width();

    return { x: x, y: y, max: max, value: value };
}