Web音乐播放
最近做了个音乐播放的功能模块,只要给标签添加一个src读取项目里的音乐文件就能进行播放,如
loop:循环播放;
autoplay:打开页面自动播放;
controls=“controls” 向用户显示控件,比如播放按钮。
【1】简易的音乐播放
当然项目不可能做得那么简陋,我的目标是模仿网易云播放器
这是html5标签原生的样式有点丑,也不符合要求,只能自己去手写
【2】手写音乐播放样式
<style type="text/css">
.slider_box {
position:absolute;
width: 100%;
background-color:#2e2e2e;
height: 80px;
box-shadow: 1px 1px 2px 2px #808080;
bottom:10px;
z-index: 10;
}
.slidearea {
position:absolute;
width: 800px;
left:340px;
top:50px;
}
.fa_controls{
position:absolute;
left:90px;
top:15px;
}
.fa_controls a{
padding:10px 15px;
}
.fa_controls .fa{
font-size: 30px;
color: #fff;
}
#pauseone i,#playing i{
font-size: 45px;
}
.fa_controls .fa:hover{
text-shadow:0px 1px 2px #fff;
}
.musicinfor{
position:absolute;
left:370px;
top:20px;
color: #fff;
font-size: 15px;
}
.musicTime{
position:absolute;
left:1180px;
top: 55px;
color: #fff;
}
.volumeControl{
position:absolute;
left:1340px;
top: 25px;
}
.volumeControl .fa{
font-size: 27px;
color: #fff;
}
.volumeSlide{
position:absolute;
left:1380px;
top: 35px;
}
.stateControl a{
position:absolute;
left:1290px;
top: 25px;
font-size: 27px;
color: #fff;
}
.slidearea {
-moz-transition: all 0s;
-o-transition: all 0s;
-webkit-transition: all 0s;
transition: all 0s;
}
.dis_none{
display: none;
}
//滑块
input[type=range]{
margin-top: 8px;
outline: none;
-webkit-appearance: none;/*清除系统默认样式*/
width:100% !important;
background: -webkit-linear-gradient(#61bd12, #61bd12) no-repeat, #ddd;
background-size: 30% 100%;/*设置左右宽度比例*/
height: 3px;/*横条的高度*/
}
/*拖动块的样式*/
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;/*清除系统默认样式*/
height:16px;/*拖动块高度*/
width: 16px;/*拖动块宽度*/
background: #fff;/*拖动块背景*/
border-radius: 50%; /*外观设置为圆形*/
border: solid 1px #ddd; /*设置边框*/
}
</style>
----------------------------------------------------------------------
<div class="slider_box">
<div class="fa_controls">
<a id="lastone" href="javascript:;" >
<i class="fa fa-step-backward"></i>
</a>
<a id="pauseone" href="javascript:;" class="" >
<i class="fa fa-play-circle-o"></i>
</a>
<a id="playing" href="javascript:;" class="dis_none" >
<i class="fa fa-pause"></i>
</a>
<a id="nextone" href="javascript:;">
<i class="fa fa-step-forward"></i>
</a>
</div>
<div class="musicinfor">
<label id="musicinfor">蓝七七 - 侧脸</label>
</div>
<div class="musicTime">
<label id="musicCurrentTime"></label>
<label id="musicTime">/</label>
<label id="musicDuration"></label>
</div>
<div class="slidearea">
<input type="range" name="range_speed" id="range_speed" value="0" oninput="changeSpeed()" />
</div>
<div class="volumeSlide">
<div id="volumeSlide" style="width:150px;"></div>
</div>
<div class="volumeControl">
<a id="volumeUp" href="javascript:;" class="">
<i class="fa fa-volume-up"></i>
</a>
<a id="volumeOff" href="javascript:;" class="dis_none">
<i class="fa fa-volume-off"></i>
</a>
</div>
<div class="stateControl">
<!----列表循环播放---->
<a id="retweet" href="javascript:;" onclick="stateControlchange()" title="顺序播放">
<i class="fa fa-retweet"></i>
</a>
<!----单曲循环播放---->
<a id="refresh" href="javascript:;" onclick="stateControlchange()" class="dis_none" title="单曲循环">
<i class="fa fa-refresh"></i>
</a>
<!----随机播放---->
<a id="random" href="javascript:;" onclick="stateControlchange()" class="dis_none" title="随机播放">
<i class="fa fa-random"></i>
</a>
<!----顺序播放---->
<a id="" href="javascript:;" onclick="stateControlchange()" class="dis_none" title="顺序播放">
<i class="fa fa-exchange"></i>
</a>
</div>
</div>
这个样式虽然也不是很漂亮,最起码比原生的好多了
【3】功能实现
这个功能该怎么实现呢?
首先我的进度条要随着音乐播放而滑动,可以通过html5标签的内置封装好的事件和属性实现(总体思想就是将html5标签的数据复制到我播放器里)
对象属性:
currentTime 获取当前播放时间
duration 获取歌曲的总时间
play 是否在播放 返回true/false
pause 是否暂停 返回true/false
对象方法:
play() 播放歌曲
pause() 暂停歌曲
load()重新加载歌曲
//音乐进度条-获取audio的播放时间比例改变进度条
function changeSpeed() {
var value = $('#range_speed').val();
var valStr = value + "% 100%";
$('#range_speed').css({
"background-size": valStr
});
progressBar.value=parseInt(value);
myCurrentTime.value=progressBar.value/100*music.duration;
music.currentTime=myCurrentTime.value;
};
//鼠标监听事件--通过鼠标事件进行滑动音乐进度条
function mouEvent(){
var range_speed=document.getElementById("range_speed");
//鼠标按下事件
range_speed.addEventListener('mousedown',function(){
clearInterval(settime);
$.ajaxSettings.async = false;
move=true;
music.pause();
},false);
//鼠标移动事件
range_speed.addEventListener('mousemove',function(){
if(move==true){
changeSpeed();
}
},false);
//鼠标松开事件
document.addEventListener('mouseup',function(){
if(move==true){
move=false;
var playing=document.getElementById("playing");
if(playing.className==""){
music.play();
}
SetTime();
}
},false);
}
//鼠标按下事件
$("#range_speed").on('mousedown', function (event) {
mouEvent();
});
//鼠标移动事件
$("#range_speed").on('mousemove', function (event) {
mouEvent();
});
//鼠标松开事件
$(document).on("mouseup", function (event) {
mouEvent();
});
//进度条自动随音乐滑动
function SetTime(){
settime=setInterval(function() {
myCurrentTime.value=music.currentTime;
var nums= myCurrentTime.value/music.duration*100;
if(isNaN(parseInt(nums))){
nums=0;
}
progressBar.value=nums;
$("#range_speed").val(nums);
var valStr = nums + "% 100%";
$('#range_speed').css({
"background-size": valStr
});
}, 1000);
}
//音乐播放时间改变
function sumTime(){
setInterval(function() {
var currentTime=music.currentTime;
var duration=music.duration;
if(isNaN(parseInt(music.duration))){
duration=0;
}
timeChange(currentTime, "musicCurrentTime");
timeChange(duration, "musicDuration");
}, 1000);
}
//播放时间格式转换
function timeChange(time, timePlace) {
//默认获取的时间是时间戳改成我们常见的时间格式
var timePlace = document.getElementById(timePlace);
//分钟
var minute = time / 60;
var minutes = parseInt(minute);
if (minutes < 10) {
minutes = "0" + minutes;
}
//秒
var second = time % 60;
seconds = parseInt(second);
if (seconds < 10) {
seconds = "0" + seconds;
}
var allTime = "" + minutes + "" + ":" + "" + seconds + ""
timePlace.textContent = allTime;
}
【4】其他
这个播放器的音量控件我是用layui的滑块的原理一样,自行参悟吧
注意音乐播放器虽然能读取项目里的音频文件,但不能直接读取本地硬盘的音频文件,我是通过后台读取音频文件,再通过流输出到页面进行播放的
//播放音乐
public void playingMusic(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=UTF-8");//处理响应编码
String range = request.getHeader("Range");
String fileUrl=request.getParameter("fileUrl");
String type=request.getParameter("type");
if("audio".equals(type)){
int musicRecordID=Integer.parseInt(request.getParameter("musicRecordID"));
int flag=imrs.update(musicRecordID);
if(flag!=1){
return;
}
}
ServletOutputStream out=null;
BufferedInputStream bfis=null;
BufferedOutputStream bfos=null;
try {
File file=new File(fileUrl);
if(file.exists()){
if(file.isFile()){
out = response.getOutputStream();
bfis=new BufferedInputStream(new FileInputStream(fileUrl));
long length = file.length();
// 播放进度
int count = 0;
// 播放百分比
int percent = (int)(length * 1);
String[] rs = range.split("\\=");
range = rs[1].split("\\-")[0];
response.addHeader("Accept-Ranges", "bytes");
response.addHeader("Content-Length", length + "");
response.addHeader("Content-Range", "bytes " + 0 + "-" + (length - 1) + "/" + length);
String mineType=this.getServletContext().getMimeType(file.getName());
response.addHeader("Content-Type", mineType+";charset=UTF-8");
bfos=new BufferedOutputStream(out);
byte[] bytes=new byte[1024];
int len=0;
while((len=bfis.read(bytes))!=-1){
bfos.write(bytes, 0, len);
count += len;
if(count >= percent){
break;
}
}
}
}
}catch (IOException e) {e.printStackTrace();}
//关闭资源
finally{
if(bfis!=null){
try {bfis.close(); } catch (IOException e) {
new RuntimeException("读取缓冲区关闭失败!!");}
}
if(bfos!=null){ try {bfos.close();} catch (IOException e) {
new RuntimeException("写入缓冲区关闭失败!!");}
}
if(out!=null){
try {out.close();} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}