如何使用 HTML 设计自定义音频播放器
How to design customized audio player with HTML
我有一个音频播放器布局,我想将其与 HTML 音频播放器元素一起使用。
我正在尝试 <audio></audio>
,它给了我默认播放器:
有什么方法可以更改播放器的样式以使用我想要使用的布局?
据我所知,您无法设置默认播放器的样式,但您可以使用 plyr.io 等插件创建自定义播放器(基于您的 audio
标签),您可以编辑插件样式随心所欲
例如:
plyr.setup(document.querySelectorAll('.js-plyr'), {});
<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>
您可以很快地为 HTML5 音频播放器创建一组非常漂亮的自定义音频控件。使用(大部分)基本的 HTML 和 CSS,以及一些简单的 Javascript 事件处理就足够了。此解决方案 fully-functional 基于提供的设计的自定义音频播放器。
完整的代码和示例可以在 jsFiddle 中找到:https://jsfiddle.net/mgaskill/zo3ede1c/。点击并随心所欲地播放它,因为它确实是一个可用的音频播放器。
玩家
播放器包括原始设计中描述的所有元素。您可以在第一张图片中看到这个(并与原始图片进行比较):
此外,我通过提供可折叠的 "info tray" 稍微扩展了设计,通过按右侧的 "More Info" 按钮隐藏和显示。您可以在第二张图片中看到部署的托盘:
当然,颜色并不相同,可能与原始设计有 pixel-specific 差异,但非常接近。我的核心技能不是 CSS,所以那里还有改进的余地。但是,它非常非常接近原始设计,并保留了该设计的所有精神、布局和功能。
工具
为了方便起见,此解决方案使用了一些外部元素。它们是:
- jQuery:因为我通常更喜欢它而不是裸 Javascript
- jQueryUI:用于曲目进度和音量控制,因为 HTML5 进度条在某些浏览器上不可用,特别是旧版本的 IE 和某些移动浏览器
- FontAwesome:对于 play/pause 和 volume/mute 按钮图形
- Noise Addicts Free MP3 Samples: for the brilliant Semper Fidelis March
HTML
HTML 采用将音频控制面板上的每个组件作为单独元素处理的方法。 HTML 布局非常普通,唯一有趣的部分实际上是使用 FontAwesome classes 来实现 play/pause 和 volume/mute 按钮的初始状态图标。
<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
样式调用 browser-specific(但不是 all-inclusive)样式来禁用控件的文本选择:
-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 进度条控件使用 pre-defined classes:
的条形颜色样式
.ui-progressbar {
background: #2B2B2B;
}
.ui-progressbar-value {
background: white;
}
div
-based 控件通过更改其显示布局来正确布局:
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
事件处理程序用于在音轨播放时更新曲目进度。这允许进度条向右增长以反映音轨中的当前位置。
volume
和 progress_bar
元素使用 jQueryUI 进度条控件初始化,click
处理程序设置为允许用户单击在内部动态更改位置。
play_button
和 mute_button
处理点击以更改播放状态 (play/pause) 或音频状态(音量 on/off)。这些处理程序动态交换适当的 FontAwesome class 以正确反映按钮上的当前状态。
最后,more_info
单击处理程序 shows/hides 信息托盘元素。 hide/show 使用 jQuery animate
进行动画处理以提供立体声 component-like 感觉,让人联想到 CD 托盘弹出。另外,它给控件带来了不错的 servo-like 感觉。因为这就是我想要它做的,除此之外没有其他原因。
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 };
}
我有一个音频播放器布局,我想将其与 HTML 音频播放器元素一起使用。
我正在尝试 <audio></audio>
,它给了我默认播放器:
有什么方法可以更改播放器的样式以使用我想要使用的布局?
据我所知,您无法设置默认播放器的样式,但您可以使用 plyr.io 等插件创建自定义播放器(基于您的 audio
标签),您可以编辑插件样式随心所欲
例如:
plyr.setup(document.querySelectorAll('.js-plyr'), {});
<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>
您可以很快地为 HTML5 音频播放器创建一组非常漂亮的自定义音频控件。使用(大部分)基本的 HTML 和 CSS,以及一些简单的 Javascript 事件处理就足够了。此解决方案 fully-functional 基于提供的设计的自定义音频播放器。
完整的代码和示例可以在 jsFiddle 中找到:https://jsfiddle.net/mgaskill/zo3ede1c/。点击并随心所欲地播放它,因为它确实是一个可用的音频播放器。
玩家
播放器包括原始设计中描述的所有元素。您可以在第一张图片中看到这个(并与原始图片进行比较):
此外,我通过提供可折叠的 "info tray" 稍微扩展了设计,通过按右侧的 "More Info" 按钮隐藏和显示。您可以在第二张图片中看到部署的托盘:
当然,颜色并不相同,可能与原始设计有 pixel-specific 差异,但非常接近。我的核心技能不是 CSS,所以那里还有改进的余地。但是,它非常非常接近原始设计,并保留了该设计的所有精神、布局和功能。
工具
为了方便起见,此解决方案使用了一些外部元素。它们是:
- jQuery:因为我通常更喜欢它而不是裸 Javascript
- jQueryUI:用于曲目进度和音量控制,因为 HTML5 进度条在某些浏览器上不可用,特别是旧版本的 IE 和某些移动浏览器
- FontAwesome:对于 play/pause 和 volume/mute 按钮图形
- Noise Addicts Free MP3 Samples: for the brilliant Semper Fidelis March
HTML
HTML 采用将音频控制面板上的每个组件作为单独元素处理的方法。 HTML 布局非常普通,唯一有趣的部分实际上是使用 FontAwesome classes 来实现 play/pause 和 volume/mute 按钮的初始状态图标。
<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
样式调用 browser-specific(但不是 all-inclusive)样式来禁用控件的文本选择:
-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 进度条控件使用 pre-defined classes:
的条形颜色样式.ui-progressbar {
background: #2B2B2B;
}
.ui-progressbar-value {
background: white;
}
div
-based 控件通过更改其显示布局来正确布局:
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
事件处理程序用于在音轨播放时更新曲目进度。这允许进度条向右增长以反映音轨中的当前位置。
volume
和 progress_bar
元素使用 jQueryUI 进度条控件初始化,click
处理程序设置为允许用户单击在内部动态更改位置。
play_button
和 mute_button
处理点击以更改播放状态 (play/pause) 或音频状态(音量 on/off)。这些处理程序动态交换适当的 FontAwesome class 以正确反映按钮上的当前状态。
最后,more_info
单击处理程序 shows/hides 信息托盘元素。 hide/show 使用 jQuery animate
进行动画处理以提供立体声 component-like 感觉,让人联想到 CD 托盘弹出。另外,它给控件带来了不错的 servo-like 感觉。因为这就是我想要它做的,除此之外没有其他原因。
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 };
}