简单地写一个功能比较全的音乐播放器

前言

因为音乐播放器是一个很可能在项目遇到的东西,早写总比晚写好。趁没事先写个。

思路

一个音乐播放器该有的东西:

  1. 封面,歌名,专辑,作者
  2. 控制器(上一首,下一首,暂停播放)
  3. 进度条(总进度,缓存进度,播放进度,播放时间,总时间,进度拖拽按钮)
  4. 播放方式(单曲循环,顺序播放,随机播放,列表循环)
  5. 声音(总声音长度,当前声音长度,声音长度拖拽按钮)
  6. 播放列表(序号,操作,歌名,歌手,专辑,时长)
  7. 提示区(各种成功错误提示)
  8. 歌词(等有时间后续开发:2019/06/10记录)
  9. 后续优化(包括但不限于加载中的进度条动画,加载中的时间显示,音乐列表的滚动条功能:2019/06/12记录)

进度

2019.06.10–仅完成1,2,3,5,7。
2019.06.12–完成1,2,3,4,5,6,7
未完待续

相关资料

B站音乐播放器(b站万岁,只要你是b站大会员我们就是朋友,欸嘿);
audio的属性与方法:https://www.jianshu.com/p/1fe701c9179f

截图

功能

暂停与播放

// 暂停与播放
play() {if (this.playing) {// 播放中,点击则为暂停this.playing = false;audio.pause();} else { // 暂停中,点击则为播放this.playing = true;audio.play();}},
音频监听初始化
// 音频事件初始化
audioInit() {let _this = this;let progressL = this.$refs.track.offsetWidth; // 进度条总长// 事件如果不需要可以不写// 音频或视频文件已经就绪可以开始,在点击播放时触发audio.addEventListener('play', () => {console.log('play');});// 浏览器开始寻找指定的音频或视频audio.addEventListener('loadstart', () => {console.log('loadstart');// 当前音量进度_this.volume = audio.volume;_this.volumeX = _this.volume * _this.$refs.trackV.offsetWidth;});// 播放位置改变时触发[注意:播放和调整指示定位时都会触发](主要事件)audio.addEventListener('timeupdate', () => {// 当前播放时间_this.currentTime = _this.timeToString(audio.currentTime);// 总播放时间_this.totalTime = _this.timeToString(audio.duration);// 当前播放进度百分比let precent = audio.currentTime / audio.duration  || 0;// 当前播放进度_this.progressScaleX = precent.toFixed(3);// 当前缓存进度// 已缓存时间let buffered = audio.buffered.length ? audio.buffered.end(audio.buffered.length-1) : 0;_this.bufferedScaleX = (buffered / audio.duration).toFixed(3);// 当前进度按钮位置_this.thumbTranslateX = (precent * progressL).toFixed(3);});// 音频或视频能够不停顿地一直播放audio.addEventListener('canplaythrough', () => {console.log('canplaythrough');});// 音频或视频的时长已改变audio.addEventListener('durationchange', () => {console.log('durationchange');_this.totalTime = _this.timeToString(audio.duration)});// 在音频或视频终止加载时触发,包括终止当前播放(未加载完)进行下一首播放时也会触发audio.addEventListener('abort', () => {console.log('abort')});// 在音频或视频加载发生错误时触发audio.addEventListener('error', () => {console.log('error');console.log('-----networkState---------',audio.networkState);console.log('-----readyState---------',audio.readyState);switch (audio.error.code) {case 1:_this.error = '未知错误';break;case 2:_this.error = '数据源发生未知错误';break;case 3:_this.error = '数据源解码错误';break;case 4:audio.networkState == 3 && (_this.error = '连接网络失败');break;}setTimeout(() => {_this.error = '';},3000)});// 播放结束audio.addEventListener("ended", ()=> {console.log("ended");switch (_this.playType) {case 1: // 列表循环_this.index = _this.index+1 >= _this.songList.length ? 0 : _this.index+1;break;case 2: // 随机播放_this.index = Math.floor(Math.random()*_this.songList.length);break;case 3: // 单曲循环break;}_this.song = _this.songList[_this.index];_this.thumbSlide = true;// 此处需要一定的延迟让audio的dom结构获取到,额,你们自己意会或者可以试着去掉看bugsetTimeout(() => {audio.play();},100);// 解决因为transition的回弹bugsetTimeout(() => {_this.thumbSlide = false;}, 1000)}, true);
},
滑动进度条
// 滑动进度条
slideProgress() {// 由于滑动事件有相同代码,所以进行了简单的封装,具体原理在注释代码中。this.slideFn('progress', this.$refs.thumb, this.$refs.track.offsetWidth);/*let thumb = this.$refs.thumb;let _this = this;thumb.onmousedown = function (e) {// 移动时暂停播放并设置transition: none,解决在滑动结束后出现回弹的bugaudio.pause();_this.thumbSlide = true;let progressL = _this.$refs.track.offsetWidth;let mouseInitX = e.clientX,mouseEndX = 0,moveX = 0,thumbInitX = _this.stringToNum(thumb.style.transform),thumbEndX = 0;document.onmousemove = function (e) {mouseEndX = e.clientX;moveX = mouseEndX - mouseInitX;let a = thumbInitX - 0 + moveX;if (moveX > 0) {thumbEndX = a > progressL ? progressL : a;} else {thumbEndX = a <= 0 ? 0 : a;}_this.progressScaleX = thumbEndX / progressL;_this.thumbTranslateX = thumbEndX;};document.onmouseup = function (e) {audio.currentTime = thumbEndX * audio.duration / progressL;audio.play();_this.thumbSlide = false;document.onmousedown = null;document.onmousemove = null;document.onmouseup = null;}}*/
},
滑动音量
// 滑动音量
slideVolume() {// 由于滑动事件有相同代码,所以进行了简单的封装,具体原理在注释代码中。this.slideFn('volume', this.$refs.thumbV, this.$refs.trackV.offsetWidth);/*let thumb = this.$refs.thumbV;let _this = this;thumb.onmousedown = function (e) {// 移动时暂停播放并设置transition: none,解决在滑动结束后出现回弹的bug_this.thumbVSlide = true;let progressL = _this.$refs.trackV.offsetWidth;let mouseInitX = e.clientX,mouseEndX = 0,moveX = 0,thumbInitX = _this.stringToNum(thumb.style.transform),thumbEndX = 0;document.onmousemove = function (e) {mouseEndX = e.clientX;moveX = mouseEndX - mouseInitX;let a = thumbInitX - 0 + moveX;if (moveX > 0) {thumbEndX = a > progressL ? progressL : a;} else {thumbEndX = a <= 0 ? 0 : a;}_this.volume = thumbEndX / progressL;_this.volumeX = thumbEndX;};document.onmouseup = function (e) {audio.volume = thumbEndX / progressL;_this.thumbVSlide = false;document.onmousedown = null;document.onmousemove = null;document.onmouseup = null;}}*/
},
上一首与下一首
// 上一首
skipBack() {this.skipFn('skipBack');
},
// 下一首
skipForward() {this.skipFn('skipForward');
},
//上下首封装
skipFn(type) {switch (this.playType) {case 2: // 随机播放this.index = Math.floor(Math.random()*this.songList.length);break;default:if (type == 'skipBack') {this.index-1>= 0? this.index -- : 0;} else {this.index = this.index+1>= this.songList.length? this.songList.length-1: this.index+1;}break;}this.song = this.songList[this.index];this.playing = true;setTimeout(() => {this.totalTime = '00:00';audio.play();},100)
},
选择播放方式
// 选择播放方式
chosePlayType() {this.playType = this.playType+1 > 3 ? 1 : this.playType+1;
},
js判断当前页面是否激活
// 解决页面切换到后台或者切换到其他页面一段时间后,切回时出现进度条回弹的bug
// 想看此bug的可以不调用该方法,并在播放之后切换到其他页面一段时间后切回,会发现进度条出现回弹的bug,因为transition的问题
setPageListen() {let _this = this;// js判断浏览当前页(关键词:当前,浏览)// 可以通过document.hidden属性判断当前页面是否是激活状态。// 兼容性:IE10+,Firefox10+,Chrome14+,Opera12.1+,Safari7.1+var hiddenProperty = 'hidden' in document ? 'hidden' :'webkitHidden' in document ? 'webkitHidden' :'mozHidden' in document ? 'mozHidden' :null;var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');var onVisibilityChange = function(){if (!document[hiddenProperty]) {document.title='被发现啦(*´∇`*)';_this.thumbSlide = true;setTimeout(() => {_this.thumbSlide = false;},300)}else{document.title='藏好啦(つд⊂)  ';}};document.addEventListener(visibilityChangeEvent, onVisibilityChange);
},
公方法
// 字符串转数字
stringToNum(str) {return Number(str.replace(/translateX\(|px\)/g , ''))
},
// 秒值转字符串
timeToString(param){param = parseInt(param);let hh = '',mm = '',ss = '';if (param>=0 && param<60) {param<10? ss = '0'+ param :ss = param;return '00:'+ ss;} else if (param>=60 && param<3600) {mm = parseInt(param/60);mm<10?mm = '0'+mm :mm;(param-parseInt(mm*60))<10?ss='0'+ String(param-parseInt(mm*60)) : ss =  param-parseInt(mm*60);return mm + ':' +ss;}
},

完整代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content=""><meta name="format-detection" content="telephone=no"><!-- android部分浏览器会缓存页面 --><meta http-equiv="Expires" content="0"><meta http-equiv="Pragma" content="no-cache"><meta http-equiv="Cache-control" content="no-cache"><meta http-equiv="Cache" content="no-cache"><title>音乐播放器</title><!--es6转es5插件--><script src="https://cdn.bootcss.com/babel-polyfill/7.4.4/polyfill.min.js" type="text/javascript"></script><!--vue--><script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script><style>/*init.style*/a, article, body, div, footer, form, h1, h2, h3, h4, h5, h6, header, html, iframe, img, input, li, p, section, span, textarea, ul, video {margin: 0;padding: 0;}</style><style>/*公共css*/.forbid-transition{transition: none !important;}</style><style>/*控制器综合*/.audioplayer{position: fixed;bottom: 0;left: 0;width: 100%;height: 60px;white-space: nowrap;background-color: #384245;color: #737A7C;font-size: 14px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;z-index: 104;}.audioplayer .ap-status{position: relative;margin: 0 auto;width: 1100px;}.audioplayer .ap-controller{display: flex;width: 100%;height: 100%;background-color: #384245;position: relative;}.audioplayer .ap-button {cursor: pointer;transition: 0.2s;}.audioplayer .ap-controller .ap-controller-left > *,.audioplayer .ap-controller .ap-controller-right > * {display: inline-flex;align-items: center;justify-content: center;height: 100%;vertical-align: middle;}svg:not(:root) {overflow: hidden;}.audioplayer svg:not(.ap-svg-exclude) {width: 28px;height: 28px;vertical-align: middle;transition: 0.2s;}.audioplayer .ap-progress-thumb svg{width: 21px;height: 19px;display: block;cursor: pointer;}.audioplayer .ap-controller .ap-controller-center .ap-buffer-bar,.audioplayer .ap-controller .ap-controller-center .ap-progress-bar{position: absolute;-webkit-transform-origin: 0 0;transform-origin: 0 0;top: 0;bottom: 0;left: 0;right: 0;transition: transform 0.5s linear, -webkit-transform 0.5s linear;}/*left*/.audioplayer .ap-controller-left .ap-cover{width: 60px;height: 60px;background: #E7E7E7;-webkit-background-size: 100% 100%;background-size: 100% 100%;cursor: pointer;}.audioplayer .ap-controller-left .ap-button{padding: 0 8px;}.audioplayer .ap-controller-left .ap-skipback-button{margin-left: 16px;}.audioplayer .ap-controller-left .ap-skipforward-button{margin-right: 16px;}/*center*/.audioplayer .ap-controller-center{padding: 10px 0;display: flex;flex: 1;flex-direction: column;overflow: hidden;}.audioplayer .ap-controller-center .ap-song-msg{}.audioplayer .ap-controller-center .ap-song-msg{display: flex;flex: 1;align-items: center;}.audioplayer .ap-controller-center .ap-song-msg .ap-name{cursor: pointer;overflow: hidden;white-space: nowrap;-ms-text-overflow: ellipsis;text-overflow: ellipsis;}.audioplayer .ap-controller-center .ap-song-msg .ap-artist{font-size: 12px;margin-left: 6px;cursor: default;white-space: nowrap;-ms-text-overflow: ellipsis;text-overflow: ellipsis;}.audioplayer .ap-controller-center .ap-song-msg .ap-time{font-size: 12px;flex: 1;text-align: right;cursor: default;min-width: 110px;}.audioplayer .ap-controller-center .ap-song-msg .ap-time .ap-current-time{color: #fff;}.audioplayer .ap-controller-center .ap-progress-line{flex: 1;display: flex;align-items: center;}.audioplayer .ap-controller-center .ap-play-track{position: relative;width: 100%;height: 3px;}.audioplayer .ap-controller-center .ap-play-bar-wrap{position: absolute;top: 0;left: 0;bottom: 0;right: 0;border-radius: 1.5px;overflow: hidden;background: #909090;}.audioplayer .ap-controller-center .ap-buffer-bar{background: rgba(50, 176, 218, 0.47);}.audioplayer .ap-controller-center .ap-progress-bar{background: #32B0DA;;}.audioplayer .ap-controller .ap-controller-center .ap-progress-thumb{transition: -webkit-transform 0.5s linear;transition: transform 0.5s linear;transition: transform 0.5s linear, -webkit-transform 0.5s linear;position: absolute;top: -5px;left: -4px;}/*right*/.audioplayer .ap-controller-right {width: 360px;padding: 0 20px;}.audioplayer .ap-controller-right .ap-line {font-size: 24px;padding: 0 8px;cursor: default;}.audioplayer .ap-controller-right .ap-button {padding: 0 8px;}.audioplayer .ap-controller-right .ap-volume-line {width: 86px;margin-right: 8px;height: 28px;}.audioplayer .ap-controller-right .ap-line-draw {height: 24px;width: 1px;background: #979797;}.audioplayer .ap-controller-right .ap-volume-track {position: relative;width: 100%;height: 3px;}.audioplayer .ap-controller-right .ap-volume-bar-wrap {position: absolute;top: 0;bottom: 0;left: 0;right: 0;border-radius: 1.5px;overflow: hidden;background: #909090;}.audioplayer .ap-controller-right .ap-volume-bar {position: absolute;-webkit-transform-origin: 0 0;transform-origin: 0 0;top: 0;bottom: 0;left: 0;right: 0;background: #32B0DA;}.audioplayer .ap-controller-right .ap-volume-thumb {position: absolute;top: -4px;left: -6px;cursor: pointer;}.audioplayer .ap-controller-right .ap-volume-thumb-dot {width: 12px;height: 12px;border-radius: 50%;background: #32B0DA;-webkit-transform: scale(0);transform: scale(0);transition: 0.2s;}.audioplayer .ap-controller-right .ap-volume-line:hover .ap-volume-thumb-dot{transform: scale(1);}.audioplayer .ap-controller-right .ap-playlist-button-bg {background: #4A5355;height: 28px;border-radius: 14px;padding: 0 8px 0 6px;}.audioplayer .ap-controller-right .ap-playlist-button-amount {color: #fff;font-size: 12px;vertical-align: middle;transition: 0.2s;}/*提示区*/.audioplayer .ap-toast {position: absolute;bottom: 72px;left: 50%;-webkit-transform: translate(-50%, 0);transform: translate(-50%, 0);padding: 10px 20px;background-color: rgba(0, 0, 0, 0.8);border-radius: 4px;color: #fff;opacity: 1;pointer-events: none;transition: 0.3s;}.audioplayer .ap-toast-hide {opacity: 0;-webkit-transform: translate(-50%, 12px);transform: translate(-50%, 12px);}</style><style>/*播放列表*/.ps {/*overflow: hidden !important;*/overflow-y: scroll;overflow-anchor: none;-ms-overflow-style: none;touch-action: auto;-ms-touch-action: auto;}ol{padding: 0;margin: 0;}.audioplayer .ap-playlist {width: 620px;position: absolute;right: 0;bottom: 60px;background-color: #384245;border-radius: 6px 6px 0 0;transition: 0.3s;-webkit-transform-origin: 0 100%;transform-origin: 0 100%;color: rgba(255, 255, 255, 0.4);font-weight: lighter;}.audioplayer .ap-playlist.ap-playlist-hide {-webkit-transform: translateY(100%);transform: translateY(100%);}.audioplayer .ap-playlist .ap-playlist-header {padding: 16px 20px 16px 20px;display: flex;cursor: default;}.audioplayer .ap-playlist .ap-playlist-header .ap-playlist-header-name {flex: 1;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}.audioplayer .ap-playlist-header .ap-playlist-header-close{font-size: 14px;margin-left: 20px;}.audioplayer .ap-playlist .ap-playlist-body {position: relative;background-color: #455155;height: 260px;}.audioplayer .ap-playlist .ap-playlist-line{display: flex;cursor: default;justify-content: space-between;}.audioplayer .ap-playlist .ap-playlist-line:hover{background: #425961;color: #50c9da;}.audioplayer .ap-playlist .ap-playlist-line.ap-playlist-line-active{background: #425961;color: #32B0DA;}.audioplayer .ap-playlist .ap-playlist-body li{padding: 10px 50px 10px 20px;transition: 0.2s;cursor: pointer;line-height: 21px;}</style>
</head>
<body>
<div id="app"><!-- 浏览器原生播放器 --><audio :src="song.url" id="audio" controls></audio><!-- 音乐播放器 --><div id="music-container" class="audioplayer"><div class="ap-status"><!-- 播放列表 --><div class="ap-playlist" :class="{'ap-playlist-hide': !listShow}"><!-- 列表头部 --><div class="ap-playlist-header"><div class="ap-playlist-header-name"><span class="ap-playlist-header-title">播放列表</span><span class="ap-playlist-header-amount">(共{{songList.length}}首)</span></div><div class="ap-playlist-header-artist">歌手</div><div class="ap-playlist-header-close" @click="handleList">×</div></div><!-- 列表内容 --><div class="ap-playlist-body ps"><ol><li class="ap-playlist-line":class="{'ap-playlist-line-active': index == i}"v-for="(li, i) in songList"@click="choseSong(li, i)":key="li.id" :data-index="i"><div class="ap-playlist-line-name">{{li.name}}-{{li.album}}</div><div class="ap-playlist-line-artist">{{li.artist}}</div></li></ol></div></div><!-- 控制器综合,包含控制器,音量,进度条等 --><div class="ap-controller"><div class="ap-controller-left"><!-- 封面 --><div class="ap-cover" :style="{backgroundImage: 'url('+song.cover+')'}"></div><!-- 上一首 --><div class="ap-button ap-skipback-button" @click="skipBack"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M20.229 24.343l-10.286-6.171c-0.914-0.571-1.486-1.371-1.486-2.171s0.571-1.714 1.486-2.171l10.286-6.171c0.914-0.571 1.829-0.686 2.629-0.229 0.686 0.457 1.143 1.257 1.143 2.286v12.571c0 1.029-0.457 1.943-1.143 2.286-0.343 0.229-0.686 0.229-1.029 0.229-0.457 0.114-1.029-0.114-1.6-0.457zM21.143 9.143l-10.286 6.171c-0.343 0.229-0.571 0.457-0.571 0.686s0.229 0.571 0.571 0.686l10.286 6.171c0.457 0.229 0.686 0.229 0.914 0.229 0.229-0.114 0.229-0.457 0.229-0.8v-12.571c0-0.457-0.114-0.686-0.229-0.8 0 0-0.114 0-0.229 0-0.229-0.114-0.457 0-0.686 0.229z"></path><path d="M8.229 7.771v16.571c0 0.457 0.343 0.914 0.914 0.914v0c0.457 0 0.914-0.343 0.914-0.914v-16.571c0-0.457-0.343-0.914-0.914-0.914v0c-0.457 0-0.914 0.343-0.914 0.914z"></path></svg></div><!-- 播放与暂停 --><div class="ap-button ap-play-button" @click="play"><svg v-if="!playing" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M22.756 16.711l-8.8 5.422c-0.444 0.267-0.978 0.089-1.244-0.267-0.089-0.178-0.089-0.267-0.089-0.444v-10.844c0-0.533 0.356-0.889 0.889-0.889 0.178 0 0.356 0.089 0.444 0.089l8.8 5.422c0.444 0.267 0.533 0.8 0.267 1.244-0.089 0.089-0.178 0.178-0.267 0.267z"></path></svg><svg v-else version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M11.556 8.889v0c0.711 0 1.333 0.622 1.333 1.333v11.556c0 0.711-0.622 1.333-1.333 1.333v0c-0.711 0-1.333-0.622-1.333-1.333v-11.556c0-0.711 0.622-1.333 1.333-1.333z"></path><path d="M21.333 8.889v0c0.711 0 1.333 0.622 1.333 1.333v11.556c0 0.711-0.622 1.333-1.333 1.333v0c-0.711 0-1.333-0.622-1.333-1.333v-11.556c0-0.711 0.622-1.333 1.333-1.333z"></path></svg></div><!-- 下一首 --><div class="ap-button ap-skipforward-button" @click="skipForward"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M10.514 24.914c-0.343 0-0.686-0.114-1.029-0.229-0.686-0.457-1.143-1.257-1.143-2.286v-12.571c0-1.029 0.457-1.943 1.143-2.286 0.686-0.457 1.714-0.343 2.629 0.229l10.286 6.171c0.914 0.571 1.486 1.371 1.486 2.171s-0.571 1.714-1.486 2.171l-10.286 6.171c-0.571 0.229-1.143 0.457-1.6 0.457zM10.514 8.8c-0.114 0-0.114 0-0.229 0-0.229 0.114-0.229 0.457-0.229 0.8v12.571c0 0.457 0.114 0.686 0.229 0.8s0.457 0.114 0.914-0.229l10.286-6.171c0.343-0.229 0.571-0.457 0.571-0.686s-0.229-0.457-0.571-0.686l-10.286-6.171c-0.343-0.114-0.571-0.229-0.686-0.229z"></path><path d="M23.086 6.857v0c-0.457 0-0.914 0.343-0.914 0.914v16.571c0 0.457 0.343 0.914 0.914 0.914v0c0.457 0 0.914-0.343 0.914-0.914v-16.571c0-0.571-0.343-0.914-0.914-0.914z"></path></svg></div></div><div class="ap-controller-center"><!-- 歌曲信息 --><div class="ap-song-msg"><span class="ap-name">{{song.name}}</span><span class="ap-artist">-{{song.artist}}</span><span class="ap-time"><span class="ap-current-time">{{currentTime}}</span><span> / </span><span class="ap-total-time">{{totalTime}}</span></span></div><!-- 进度条 --><div class="ap-progress-line"><div class="ap-play-track" ref="track"><!-- 总进度 --><div class="ap-play-bar-wrap"><!-- 缓存进度 --><div class="ap-buffer-bar" :style="{transform: 'scaleX('+bufferedScaleX+')'}"></div><!-- 当前进度 --><div class="ap-progress-bar" :class="{'forbid-transition': thumbSlide}" :style="{transform: 'scaleX('+progressScaleX+')'}"></div></div><!-- 进度按钮 --><div class="ap-progress-thumb" :class="{'forbid-transition': thumbSlide}" ref="thumb" :style="{transform: 'translateX('+thumbTranslateX+'px)'}"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 32" class="ap-svg-exclude"><path fill="#32b0da" opacity="0.28" d="M11.789 1.207h11.789c3.72 0 6.737 3.016 6.737 6.737v8.421c0 3.72-3.016 6.737-6.737 6.737h-11.789c-3.72 0-6.737-3.016-6.737-6.737v-8.421c0-3.72 3.016-6.737 6.737-6.737z"></path><path fill="#32b0da" opacity="0.14" d="M12.211 2.050h10.947c3.488 0 6.316 2.828 6.316 6.316v7.579c0 3.488-2.828 6.316-6.316 6.316h-10.947c-3.488 0-6.316-2.828-6.316-6.316v-7.579c0-3.488 2.828-6.316 6.316-6.316z"></path><path fill="#000" d="M22.737 2.969c3.256 0 5.895 2.627 5.895 5.866v6.705c0 3.24-2.639 5.866-5.895 5.866h-10.105c-3.256 0-5.895-2.626-5.895-5.866v-6.705c0-3.239 2.639-5.866 5.895-5.866h10.105z"></path><path fill="#fff" d="M22.737 2.969c3.256 0 5.895 2.627 5.895 5.866v6.705c0 3.24-2.639 5.866-5.895 5.866h-10.105c-3.256 0-5.895-2.626-5.895-5.866v-6.705c0-3.239 2.639-5.866 5.895-5.866h10.105z"></path><path fill="#333" d="M13.053 9.706c0.697 0 1.263 0.566 1.263 1.263v2.526c0 0.697-0.566 1.263-1.263 1.263s-1.263-0.566-1.263-1.263v-2.526c0-0.697 0.566-1.263 1.263-1.263z"></path><path fill="#333" d="M22.316 9.706c0.697 0 1.263 0.566 1.263 1.263v2.526c0 0.697-0.566 1.263-1.263 1.263s-1.263-0.566-1.263-1.263v-2.526c0-0.697 0.566-1.263 1.263-1.263z"></path><path fill="#333" d="M26.947 15.538c0 2.321-1.89 4.211-4.211 4.211h-10.105c-2.321 0-4.211-1.89-4.211-4.211v-6.737c0-2.323 1.89-4.211 4.211-4.211h10.105c2.321 0 4.211 1.888 4.211 4.211v6.737zM23.020 2.935l0.6-1.041c0.349-0.603 0.143-1.376-0.461-1.725s-1.376-0.141-1.725 0.461l-1.314 2.275h-4.871l-1.314-2.275c-0.349-0.603-1.122-0.81-1.725-0.461-0.605 0.349-0.812 1.122-0.463 1.725l0.601 1.041c-3.121 0.15-5.612 2.708-5.612 5.866v6.737c0 3.256 2.639 5.895 5.895 5.895h10.105c3.256 0 5.895-2.639 5.895-5.895v-6.737c0-3.16-2.491-5.716-5.612-5.866z"></path></svg></div></div></div></div><div class="ap-controller-right"><!-- 竖线 --><div class="ap-line"><div class="ap-line-draw"></div></div><!-- 音量 --><div class="ap-button ap-volume-button"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M16.571 27.429c-0.457 0-0.8-0.114-1.143-0.457l-5.943-5.257h-2.743c-1.257 0-2.286-1.029-2.286-2.286v-5.829c0-1.257 1.029-2.286 2.286-2.286h2.743l5.943-5.257c0.686-0.571 1.829-0.571 2.4 0.114 0.229 0.343 0.457 0.686 0.457 1.143v18.286c0 1.029-0.8 1.829-1.714 1.829zM6.857 13.143c-0.343 0-0.571 0.229-0.571 0.571v5.829c0 0.343 0.229 0.571 0.571 0.571h3.429l6.4 5.714v-18.171l-6.4 5.6h-3.429z"></path><path d="M22.154 21.797c1.714-1.45 2.703-3.532 2.703-5.797 0-2.247-0.864-4.207-2.449-5.66-0.349-0.32-0.891-0.296-1.211 0.053s-0.296 0.891 0.053 1.211c1.232 1.129 1.893 2.631 1.893 4.397 0 1.755-0.763 3.361-2.097 4.489-0.361 0.306-0.406 0.847-0.101 1.208s0.847 0.406 1.208 0.101z"></path><path d="M25.355 24.539c2.517-2.139 3.959-5.253 3.959-8.653 0-3.22-1.389-6.329-3.697-8.509-0.344-0.325-0.887-0.31-1.212 0.035s-0.31 0.887 0.035 1.212c1.971 1.861 3.16 4.523 3.16 7.263 0 2.896-1.221 5.533-3.355 7.347-0.361 0.307-0.405 0.848-0.098 1.208s0.848 0.405 1.208 0.098z"></path></svg></div><!-- 音量进度条 --><div class="ap-volume-line"><div class="ap-volume-track" ref="trackV"><div class="ap-volume-bar-wrap"><div class="ap-volume-bar" :class="{'forbid-transition': thumbVSlide}" :style="{transform: 'scaleX('+volume+')'}"></div></div><div class="ap-volume-thumb" ref="thumbV" :class="{'forbid-transition': thumbVSlide}" :style="{transform: 'translateX('+volumeX+'px)'}"><div class="ap-volume-thumb-dot"></div></div></div></div><!-- 播放模式 --><div class="ap-button ap-order-button" @click="chosePlayType"><!-- 列表循环 --><svg v-if="playType == 1" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M25.6 15.657c-0.343 0-0.686 0.343-0.686 0.686 0 0.114 0 0.229 0 0.229v1.829c0 2.4-1.829 4.229-4.229 4.229h-10.286l0.914-0.8c0.114-0.114 0.229-0.343 0.229-0.457 0-0.343-0.343-0.686-0.686-0.686-0.229 0-0.457 0.114-0.571 0.229l-2.057 1.829-0.8 0.686 2.857 2.514c0.114 0.229 0.343 0.343 0.571 0.343 0.457 0 0.8-0.229 0.8-0.686 0-0.229-0.114-0.457-0.343-0.571l-1.029-0.914v-0.114h10.4c3.086 0 5.6-2.514 5.6-5.6v-1.829c0-0.114 0-0.114 0-0.229 0-0.343-0.343-0.686-0.686-0.686zM8.229 16.571v-1.829c0-2.4 1.829-4.229 4.229-4.229h10.971l-0.914 0.914c-0.229 0.114-0.343 0.343-0.343 0.571 0 0.343 0.343 0.686 0.8 0.686 0.229 0 0.457-0.114 0.571-0.343l1.486-1.371 1.257-1.257-2.743-2.629c-0.229-0.114-0.457-0.229-0.686-0.229-0.457 0-0.686 0.343-0.686 0.8 0 0.229 0.114 0.343 0.229 0.571l0.914 0.8v0.114h-10.971c-2.971 0-5.486 2.514-5.486 5.6v1.829c0 0.114 0 0.114 0 0.229 0 0.343 0.343 0.686 0.686 0.686s0.686-0.343 0.686-0.686c0-0.114 0-0.229 0-0.229z"></path></svg><!-- 随机播放 --><svg v-else-if="playType == 2" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M17.6 15.543c0.229 0 0.457-0.114 0.571-0.229l2.629-2.4c0.914-0.8 2.171-1.257 3.429-1.486l-1.029 0.914c-0.229 0.114-0.343 0.343-0.343 0.457 0 0.343 0.343 0.686 0.8 0.686 0.229 0 0.457-0.114 0.686-0.229l3.086-2.4-3.086-2.514c-0.114-0.229-0.343-0.343-0.571-0.343-0.457 0-0.914 0.229-0.914 0.686 0 0.229 0.114 0.457 0.343 0.571v0l1.029 0.8c-1.714 0.114-3.314 0.8-4.457 1.829l-2.629 2.4c-0.114 0.114-0.229 0.343-0.229 0.457 0 0.229 0.114 0.343 0.229 0.457 0.114 0.343 0.343 0.343 0.457 0.343zM14.057 17.486c-0.229 0-0.457 0.114-0.571 0.229l-2.743 2.514c-1.143 0.914-2.629 1.371-4.114 1.371 0 0 0 0 0 0-0.457 0-0.8 0.343-0.8 0.686s0.343 0.686 0.8 0.686c0 0 0 0 0 0 1.943 0 3.771-0.571 5.257-1.829l2.857-2.514c0.114-0.114 0.229-0.343 0.229-0.457 0-0.229-0.114-0.343-0.229-0.457-0.229-0.114-0.457-0.229-0.686-0.229zM23.771 19.543c-0.457 0-0.8 0.343-0.8 0.686 0 0.229 0.114 0.343 0.343 0.457l1.029 0.8c-1.029-0.114-2.057-0.457-2.857-1.029l-9.029-8.229c-1.486-1.371-3.543-2.171-5.714-2.171-0.571 0-1.029 0.343-1.029 0.686s0.457 0.686 0.914 0.686c1.714 0 3.429 0.686 4.571 1.714l9.029 8.229 0.229 0.114c1.143 0.8 2.514 1.257 4 1.486l-1.143 0.914c-0.343 0.114-0.457 0.343-0.457 0.571 0 0.343 0.343 0.686 0.8 0.686 0.229 0 0.457-0.114 0.571-0.343l3.086-2.514-3.086-2.629c0-0.114-0.229-0.114-0.457-0.114z"></path></svg><!-- 单曲循环 --><svg v-else version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M25.6 15.657c-0.343 0-0.686 0.343-0.686 0.686 0 0.114 0 0.229 0 0.229v1.829c0 2.4-1.829 4.229-4.229 4.229h-10.286l0.914-0.8c0.114-0.114 0.229-0.343 0.229-0.457 0-0.343-0.343-0.686-0.686-0.686-0.229 0-0.457 0.114-0.571 0.229l-2.057 1.829-0.8 0.686 2.857 2.514c0.114 0.229 0.343 0.343 0.571 0.343 0.457 0 0.8-0.229 0.8-0.686 0-0.229-0.114-0.457-0.343-0.571l-1.029-0.914v-0.114h10.4c3.086 0 5.6-2.514 5.6-5.6v-1.829c0-0.114 0-0.114 0-0.229 0-0.343-0.343-0.686-0.686-0.686zM8.229 16.571v-1.829c0-2.4 1.829-4.229 4.229-4.229h10.971l-0.914 0.914c-0.229 0.114-0.343 0.343-0.343 0.571 0 0.343 0.343 0.686 0.8 0.686 0.229 0 0.457-0.114 0.571-0.343l1.486-1.371 1.257-1.257-2.743-2.629c-0.229-0.114-0.457-0.229-0.686-0.229-0.457 0-0.686 0.343-0.686 0.8 0 0.229 0.114 0.343 0.229 0.571l0.914 0.8v0.114h-10.971c-2.971 0-5.486 2.514-5.486 5.6v1.829c0 0.114 0 0.114 0 0.229 0 0.343 0.343 0.686 0.686 0.686s0.686-0.343 0.686-0.686c0-0.114 0-0.229 0-0.229z"></path><path d="M18.286 20v-6.857h-1.257l-2.171 1.714 0.457 1.257 1.486-0.914v4.8z"></path></svg></div><!-- 播放列表 --><div class="ap-button ap-playlist-button" @click="handleList"><div class="ap-playlist-button-bg"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M5.371 6.857h9.943c0.457 0 0.8 0.343 0.8 0.8v0c0 0.457-0.343 0.8-0.8 0.8h-9.943c-0.457 0-0.8-0.343-0.8-0.8v0c0-0.457 0.343-0.8 0.8-0.8z"></path><path d="M5.371 11.086h7.429c0.457 0 0.914 0.343 0.914 0.8v0c0 0.457-0.343 0.8-0.8 0.8h-7.543c-0.457 0-0.8-0.343-0.8-0.8v0c0-0.457 0.343-0.8 0.8-0.8z"></path><path d="M5.371 15.2h5.829c0.457 0 0.8 0.343 0.8 0.8v0c0 0.457-0.343 0.8-0.8 0.8h-5.829c-0.457 0.114-0.8-0.343-0.8-0.8v0c0-0.343 0.343-0.8 0.8-0.8z"></path><path d="M20.571 6.857v0c0.457 0 0.8 0.343 0.8 0.8v14.057c0 0.457-0.343 0.8-0.8 0.8v0c-0.457 0-0.8-0.343-0.8-0.8v-14.057c0-0.457 0.457-0.8 0.8-0.8z"></path><path d="M20.914 8.457c0 0 0.114 0 0.229 0.114 0.229 0.114 0.571 0.229 0.914 0.343 0.914 0.457 1.943 1.257 2.743 2.286 0.343 0.343 0.686 0.8 0.914 1.257 0.229 0.343 0.8 0.457 1.143 0.229s0.457-0.8 0.229-1.143c-0.343-0.571-0.686-1.029-1.029-1.486-0.914-1.143-2.057-2.057-3.2-2.514-0.686-0.343-1.257-0.571-1.6-0.571-0.457-0.114-0.914 0.229-0.914 0.686-0.114 0.343 0.114 0.8 0.571 0.8z"></path><path d="M17.371 24.686c1.371 0 2.4-1.143 2.4-2.4s-1.143-2.4-2.4-2.4-2.514 1.029-2.514 2.4 1.143 2.4 2.514 2.4zM17.371 26.286c-2.286 0-4.114-1.829-4.114-4s1.829-4 4.114-4 4.114 1.829 4.114 4-1.829 4-4.114 4z"></path></svg><span class="ap-playlist-button-amount">{{songList.length}}</span></div></div></div></div><!-- 提示区 --><div class="ap-toast" :class="{'ap-toast-hide': error.length<=0}">{{error}}</div></div></div>
</div>
<script>/** 参考资料:* https://www.jianshu.com/p/1fe701c9179f* */let audio = '';var vm = new Vue({el: '#app',data() {return {playing: false, // 播放状态index: 0, // 当前播放歌曲在列表中的下标id: 2, // 当前播放歌曲的id(此处貌似没有用到)currentTime: '00:00', // 当前播放时间totalTime: '00:00', // 总播放时间bufferedScaleX: 0, // 缓存进度progressScaleX: 0, // 播放进度thumbTranslateX: 0, // 进度条滑块位置volume: 1, // 音量进度volumeX: 0, // 音量滑块位置thumbSlide: false, // 进度条滑块滑动时标记thumbVSlide: false, // 音量滑块滑动时标记error: '', // 报错内容playType: 1, // 播放类型:1-列表循环,2-随机播放,3-单曲循环listShow: false, // 播放列表是否展示song: { // 当前播放歌曲信息cover: '',name: '',artist: '',time: '',url: '',},songList: [ // 歌曲列表{id: 1,name: '刚烈女子',time: '04:31',artist: '锦零',album: '?',cover: 'http://img.ytmp3.cn/image/32.jpg',url: 'http://www.ytmp3.cn/down/58151.mp3',},{id: 2,name: '绿色',time: '04:22',artist: '陈凝雪',album: 'lvse',cover: 'http://p2.music.126.net/R4ZP3AJ9xV0vvw8LX7AbMA==/109951163860425334.jpg',url: 'http://www.ytmp3.cn/down/60380.mp3',},{id: 3,name: '青衣',time: '04:22',artist: '马天宇',album: '(*^_^*)',cover: 'http://img.ytmp3.cn/image/5.jpg',url: 'http://www.ytmp3.cn/down/43680.mp3',},{id: 4,name: '风筝误',time: '04:31',artist: '刘珂矣',album: '?',cover: 'http://img.ytmp3.cn/image/52.jpg',url: 'http://www.ytmp3.cn/down/46644.mp3',},{id: 5,name: '红昭愿(Cover 音阙诗听)',time: '04:31',artist: '锦零',album: '红昭愿',cover: 'http://img.ytmp3.cn/image/18.jpg',url: 'http://www.ytmp3.cn/down/46633.mp3',},{id: 6,name: '故城',time: '04:31',artist: '银临',album: '世俗',cover: 'http://img.ytmp3.cn/image/39.jpg',url: 'http://www.ytmp3.cn/down/46641.mp3',},{id: 7,name: '白山茶',time: '04:31',artist: '陈雪凝',album: '?',cover: 'http://img.ytmp3.cn/image/5.jpg',url: 'http://www.ytmp3.cn/down/44355.mp3',}],}},mounted() {// audio的DOM结构获取需要在mounted中,在created中话会变成 <audio :src="song.url" id="audio" controls autoplay></audio>audio = document.getElementById('audio');this.getData();this.setPageListen();},methods: {// 获取数据,并放入当前播放列表getData() {this.song = this.songList[0];// 初始化音频的监听事件this.audioInit();// 初始化进度条与音量的鼠标滑动事件this.slideProgress();this.slideVolume();},// 暂停与播放play() {if (this.playing) {// 播放中,点击则为暂停this.playing = false;audio.pause();} else { // 暂停中,点击则为播放this.playing = true;audio.play();}},// 音频事件初始化audioInit() {let _this = this;let progressL = this.$refs.track.offsetWidth; // 进度条总长// 事件如果不需要可以不写// 音频或视频文件已经就绪可以开始,在点击播放时触发audio.addEventListener('play', () => {console.log('play');});// 浏览器开始寻找指定的音频或视频audio.addEventListener('loadstart', () => {console.log('loadstart');// 当前音量进度_this.volume = audio.volume;_this.volumeX = _this.volume * _this.$refs.trackV.offsetWidth;});// 播放位置改变时触发[注意:播放和调整指示定位时都会触发](主要事件)audio.addEventListener('timeupdate', () => {// 当前播放时间_this.currentTime = _this.timeToString(audio.currentTime);// 总播放时间_this.totalTime = _this.timeToString(audio.duration);// 当前播放进度百分比let precent = audio.currentTime / audio.duration  || 0;// 当前播放进度_this.progressScaleX = precent.toFixed(3);// 当前缓存进度// 已缓存时间let buffered = audio.buffered.length ? audio.buffered.end(audio.buffered.length-1) : 0;_this.bufferedScaleX = (buffered / audio.duration).toFixed(3);// 当前进度按钮位置_this.thumbTranslateX = (precent * progressL).toFixed(3);});// 音频或视频能够不停顿地一直播放audio.addEventListener('canplaythrough', () => {console.log('canplaythrough');});// 音频或视频的时长已改变audio.addEventListener('durationchange', () => {console.log('durationchange');_this.totalTime = _this.timeToString(audio.duration)});// 在音频或视频终止加载时触发,包括终止当前播放(未加载完)进行下一首播放时也会触发audio.addEventListener('abort', () => {console.log('abort')});// 在音频或视频加载发生错误时触发audio.addEventListener('error', () => {console.log('error');console.log('-----networkState---------',audio.networkState);console.log('-----readyState---------',audio.readyState);switch (audio.networkState) {case '0':_this.error = '尚未初始化';break;case '1':_this.error = '正在下载数据';break;case '3':_this.error = '未找到资源';break;}audio.readyState == '0' && (_this.error = '音频地址错误');setTimeout(() => {_this.error = '';},3000)});// 播放结束audio.addEventListener("ended", ()=> {console.log("ended");switch (_this.playType) {case 1: // 列表循环_this.index = _this.index+1 >= _this.songList.length ? 0 : _this.index+1;break;case 2: // 随机播放_this.index = Math.floor(Math.random()*_this.songList.length);break;case 3: // 单曲循环break;}_this.song = _this.songList[_this.index];_this.thumbSlide = true;// 此处需要一定的延迟让audio的dom结构获取到,额,你们自己意会或者可以试着去掉看bugsetTimeout(() => {audio.play();},100);// 解决因为transition的回弹bugsetTimeout(() => {_this.thumbSlide = false;}, 1000)}, true);},// 滑动进度条slideProgress() {// 由于滑动事件有相同代码,所以进行了简单的封装,具体原理在注释代码中。this.slideFn('progress', this.$refs.thumb, this.$refs.track.offsetWidth);/*let thumb = this.$refs.thumb;let _this = this;thumb.onmousedown = function (e) {// 移动时暂停播放并设置transition: none,解决在滑动结束后出现回弹的bugaudio.pause();_this.thumbSlide = true;let progressL = _this.$refs.track.offsetWidth;let mouseInitX = e.clientX,mouseEndX = 0,moveX = 0,thumbInitX = _this.stringToNum(thumb.style.transform),thumbEndX = 0;document.onmousemove = function (e) {mouseEndX = e.clientX;moveX = mouseEndX - mouseInitX;let a = thumbInitX - 0 + moveX;if (moveX > 0) {thumbEndX = a > progressL ? progressL : a;} else {thumbEndX = a <= 0 ? 0 : a;}_this.progressScaleX = thumbEndX / progressL;_this.thumbTranslateX = thumbEndX;};document.onmouseup = function (e) {audio.currentTime = thumbEndX * audio.duration / progressL;audio.play();_this.thumbSlide = false;document.onmousedown = null;document.onmousemove = null;document.onmouseup = null;}}*/},// 滑动音量slideVolume() {// 由于滑动事件有相同代码,所以进行了简单的封装,具体原理在注释代码中。this.slideFn('volume', this.$refs.thumbV, this.$refs.trackV.offsetWidth);/*let thumb = this.$refs.thumbV;let _this = this;thumb.onmousedown = function (e) {// 移动时暂停播放并设置transition: none,解决在滑动结束后出现回弹的bug_this.thumbVSlide = true;let progressL = _this.$refs.trackV.offsetWidth;let mouseInitX = e.clientX,mouseEndX = 0,moveX = 0,thumbInitX = _this.stringToNum(thumb.style.transform),thumbEndX = 0;document.onmousemove = function (e) {mouseEndX = e.clientX;moveX = mouseEndX - mouseInitX;let a = thumbInitX - 0 + moveX;if (moveX > 0) {thumbEndX = a > progressL ? progressL : a;} else {thumbEndX = a <= 0 ? 0 : a;}_this.volume = thumbEndX / progressL;_this.volumeX = thumbEndX;};document.onmouseup = function (e) {audio.volume = thumbEndX / progressL;_this.thumbVSlide = false;document.onmousedown = null;document.onmousemove = null;document.onmouseup = null;}}*/},// 上一首skipBack() {this.skipFn('skipBack');},// 下一首skipForward() {this.skipFn('skipForward');},// 选择播放方式chosePlayType() {this.playType = this.playType+1 > 3 ? 1 : this.playType+1;},// 解决页面切换到后台或者切换到其他页面一段时间后,切回时出现进度条回弹的bug// 想看此bug的可以不调用该方法,并在播放之后切换到其他页面一段时间后切回,会发现进度条出现回弹的bug,因为transition的问题setPageListen() {let _this = this;// js判断浏览当前页(关键词:当前,浏览)// 可以通过document.hidden属性判断当前页面是否是激活状态。// 兼容性:IE10+,Firefox10+,Chrome14+,Opera12.1+,Safari7.1+var hiddenProperty = 'hidden' in document ? 'hidden' :'webkitHidden' in document ? 'webkitHidden' :'mozHidden' in document ? 'mozHidden' :null;var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');var onVisibilityChange = function(){if (!document[hiddenProperty]) {document.title='被发现啦(*´∇`*)';_this.thumbSlide = true;setTimeout(() => {_this.thumbSlide = false;},300)}else{document.title='藏好啦(つд⊂)  ';}};document.addEventListener(visibilityChangeEvent, onVisibilityChange);},// 是否显示播放列表handleList() {this.listShow = !this.listShow;},// 列表选歌choseSong(li, i) {this.song = li;this.index = i;this.playing = true;setTimeout(() => {audio.play();},100)},//上下首封装skipFn(type) {switch (this.playType) {case 2: // 随机播放this.index = Math.floor(Math.random()*this.songList.length);break;default:if (type == 'skipBack') {this.index-1>= 0? this.index -- : 0;} else {this.index = this.index+1>= this.songList.length? this.songList.length-1: this.index+1;}break;}this.song = this.songList[this.index];this.playing = true;setTimeout(() => {this.totalTime = '00:00';audio.play();},100)},// 滑动封装slideFn(type, thumbDom, progressLength) {let thumb = thumbDom;let _this = this;thumb.onmousedown = function (e) {// 移动时暂停播放并设置transition: none,解决在滑动结束后出现回弹的bugif (type == 'progress') {audio.pause();_this.thumbSlide = true;} else {_this.thumbVSlide = true;}let progressL = progressLength;let mouseInitX = e.clientX,mouseEndX = 0,moveX = 0,thumbInitX = _this.stringToNum(thumb.style.transform),thumbEndX = 0;document.onmousemove = function (e) {mouseEndX = e.clientX;moveX = mouseEndX - mouseInitX;let a = thumbInitX - 0 + moveX;if (moveX > 0) {thumbEndX = a > progressL ? progressL : a;} else {thumbEndX = a <= 0 ? 0 : a;}if (type == 'progress') {_this.progressScaleX = thumbEndX / progressL;_this.thumbTranslateX = thumbEndX;} else {_this.volume = thumbEndX / progressL;_this.volumeX = thumbEndX;}};document.onmouseup = function (e) {if (type == 'progress') {audio.currentTime = thumbEndX * audio.duration / progressL;audio.play();_this.thumbSlide = false;} else {audio.volume = thumbEndX / progressL;_this.thumbVSlide = false;}document.onmousedown = null;document.onmousemove = null;document.onmouseup = null;}}},// 字符串转数字stringToNum(str) {return Number(str.replace(/translateX\(|px\)/g , ''))},// 秒值转字符串timeToString(param){param = parseInt(param);let hh = '',mm = '',ss = '';if (param>=0 && param<60) {param<10? ss = '0'+ param :ss = param;return '00:'+ ss;} else if (param>=60 && param<3600) {mm = parseInt(param/60);mm<10?mm = '0'+mm :mm;(param-parseInt(mm*60))<10?ss='0'+ String(param-parseInt(mm*60)) : ss =  param-parseInt(mm*60);return mm + ':' +ss;}},}});</script>
</body>
</html>

用vue简单写一个音乐播放器相关推荐

  1. animation基础练习源码_用vue简单写一个音乐播放组件「附源码」

    作者:vipbic 转发链接:https://segmentfault.com/a/1190000022980992 前言 上次小编也分享一个关于Vue 开发过音乐播放对项目: 基于 electron ...

  2. 写一个音乐播放器的微信小程序

    要创建一个音乐播放器的微信小程序,您需要熟悉微信小程序的开发环境和语言(如 JavaScript 和 WXML/WXSS). 具体来说,您需要做以下几件事: 设计音乐播放器的用户界面,并使用 WXML ...

  3. 用Kotlin写一个音乐播放器

    添加依赖 implementation "org.jetbrains.anko:anko:0.10.8" class home_frame : Fragment() {overri ...

  4. java写一个音乐播放器源码_求一个JAVA音乐播放器的源代码

    展开全部 import javax.media.ControllerEvent; import javax.media.ControllerListener; import javax.media.E ...

  5. 300行代码写一个音乐播放器小程序

    刚进公司不久,因为公司部门年后业务拓展的关系,可能在年后会被分配到公司的微信公众号组做小程序相关的开发工作,因此写了个微信小程序wx-audio踩坑.目前还有一些功能没有写完:如返回多首歌曲.控制播放 ...

  6. 项目: 用C语言写一个音乐播放器

    目录 最终效果 代码 资源地址 最终效果 代码 /************ 音乐文件中 1开头的是周杰伦的歌 2开头的是林俊杰的歌 3开头的是许嵩的歌 *************/ #include& ...

  7. 一个VC写的音乐播放器

    以前,一直想写一个音乐播放器,但VC还没有完全学完,有些东西还练的很少,实力还不够,这是学完VC后,练习了很多东西,看了不少VC的知识,所以才决定写的. 这是2013年3月份写的,当时没有写在博客中, ...

  8. 一个vue组件完成的音乐播放器

    最近用vuepress搭建了一个文档博客,感觉网站过于简洁,想加个音乐播放插件进去,后来找到aplayer插件,但是样式风格过于死板,和我的网站有违和感,于是手动写了一个音乐播放器. 使用aplaye ...

  9. python + vue + electron实现本地音乐播放器

    前言 因为受够了一般音乐播放软件的各种没什么用的功能以及各种垃圾广告,所以想自己搞一个音乐播放器来用,花了几天时间就搞了这么个东西,跟大家分享一下. 这个文档并不是针对前端新手的,所以如果你接触前端不 ...

最新文章

  1. 【深度学习】一文看尽深度学习各领域最新突破
  2. 课程分类管理-添加课程分类
  3. 微软Azure的access control - IAM
  4. python学习-字典(哈希表、创建、插值、取值、keys、values、items、copy、fromkeys)
  5. AtCoder Regular Contest 125
  6. (32) css—opcity属性
  7. 女生长胖是一种什么样的体验?
  8. postman 指定响应格式_牛鹭学院:Postman接口测试方法,新手必看!
  9. python 宏定义_「Rust笔记」Rust之自定义宏写法
  10. Fitts’ Law / 菲茨定律
  11. 【优化求解】基于matlab蚁群算法求解函数极值问题【含Matlab源码 1201期】
  12. Ubuntu20.04安装ROS教程(虚拟机/双系统,含报错解决)
  13. 银监计算机类考试题库,干货!国考银监会财经类面试题库
  14. python写出租车计费系统_基于VHDL的出租车计费器
  15. hdu5294Tricks Device 最大流之最小割
  16. 有T2 表中的数据,求出NAME中每组累加 / 每组总数的比例大于0.6 的id 和name
  17. SNARK性能及安全——Verifier篇
  18. 【宋红康 MySQL数据库 】【高级篇】【06】MySQL的逻辑架构
  19. 快讯:我国高中数学课本即将发生全面变革,微积分下放高中不是梦!
  20. pytorch版 RGB_to_HSV和HSV_to_RGB

热门文章

  1. java打印一个空心六边形_六边形架构 Java 实现
  2. 计算彩色图像的直方图
  3. 分布式原理:一文了解 Gossip 协议
  4. 直播粉丝统计平台 抖音直播粉丝 如何查看直播间的粉丝人数 如何查看主播直播数据记录
  5. 1217: 青蛙(二)
  6. C语言每日一练——第35天:打印菱形
  7. 【问答】用SVG矢量图形自定义不规则控件——中国地图
  8. spark常用的linux命令,GitHub - Sparkinzy/linux-command: Linux命令大全搜索工具,内容包含Linux命令手册、详解、学习、搜集。...
  9. iPhone 12手机真实信号强度查看方法教程
  10. 【Unity】Obi插件系列(一)—— 总览、Actors与Solvers