项目地址:github.com/ermu5922752…css
演示地址:ermu592275254.github.io/MiniMusicPl…(歌曲连接已失效)html
作音乐播放器,界面必定要炫酷。太low了听歌没感受。自己是为了在上班的时候用,因而作成了一个相似网易云音乐的界面,大小合适。不用兼容手机端。vue
用css作图标html5
本怀着简单实用的需求去考虑,图标可用SVG、url或者css。相对于url,SVG和css更好一些。为了修炼,最终选择的css。利用好after和before,能减小不少dom嵌套。node
.next {
position: relative;
display: inline-block;
height: 36px;
width: 36px;
border: 2px solid #fff;
border-radius: 20px;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
}
.next:before {
content: '';
height: 0;
width: 0;
display: block;
border: 10px transparent solid;
border-right-width: 0;
border-left-color: #fff;
position: absolute;
top: 8px;
left: 10px;
}
.next:after {
content: '';
height: 20px;
width: 4px;
display: block;
background: #fff;
position: absolute;
top: 8px;
left: 22px;
}
复制代码
画一个唱片webpack
网易云的唱片很好看,我也要弄一个唱片! 用好box-shadow,一个元素即可以作成很好看的唱片效果。css3
.disc {
position: relative;
margin-top: 10%;
margin-left: 10%;
width: 300px;
height: 300px;
border-radius: 300px;
transform: rotate(45deg);
background-image: radial-gradient(5em 30em ellipse, #fff, #000);
border: 2px solid #131313;
box-shadow: 0 0 0 10px #343935;
opacity: 0.7;
}
复制代码
用range作进度条git
audio自己的样式很难看,而且不一样的浏览器呈现出来的效果也不同。固然你能够修改audio的样式,传统的作法是经过controls属性来隐藏audio,而后用div来代替。如今是html5时代了,固然要用更符合场景的新元素————range。github
input[type=range] {
-webkit-appearance: none;
width: 80%;
height: 8px;
border-radius: 10px;
background-color: #fff;
}
input[type=range]::-webkit-slider-thumb{
-webkit-appearance: none;
}
input[type=range]::-webkit-slider-runnable-track {
height: 8px;
border-radius: 20px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
margin-top: -3px;
height: 14px;
width: 14px;
background: #eb7470;
border-radius: 50%;
border: solid 3px #fff;
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.5);
}
复制代码
背景滤镜模糊web
将图片设置为背景的感受很棒,能够说整个播放器的颜值这背景提供了一半。设置也很是简单,用到了css3的滤镜。
.bg-blur {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
filter: blur(20px);
z-index: -1;
}
复制代码
背景图片经过js控制。
<div class="bg-blur" :style="`background-image:url(${currentSong.album_logo})`"></div>
复制代码
直接去虾米官网打开network,将url复制到postman里面去作请求。经过修改headers发现,会校验Referer。也就是说只有虾米容许的域名能够访问此接口。 http://api.xiami.com/web?v=2.0&app_key=1&key=aliez&page=1&limit=5&callback=jsonp154&r=search/songs
由于接口支持jsonp。起初尝试将chrome浏览器设置跨域,而后经过$.ajax去作一个jsonp的请求。能够正常访问。
以后忽然不行了,是否是虾米作了限制?
遂改用node启动一个服务,去伪造referer发起请求,再将请求转发到页面。无心中写了一个代理。
...
case '/song':
let songOptions = {
url: 'http://api.xiami.com/web?'+ urlArr[1],
headers: {
'Referer': 'http://m.xiami.com/'
}
};
function callback1(error, response, body) {
if (!error && response.statusCode == 200) {
res.end(body);
}
}
request(songOptions, callback1);
break;
...
复制代码
做为一款逼格比较高的播放器,歌词滚动是必须的。
将每一句歌词保存为一个对象,有对应的时间。当歌曲播放的当前时长大于或等于歌词的时间,小于此歌词的下一句歌词的时间,那么就将此歌词滚动到可视区域。而且修改字体颜色。
接口返回的歌词一脸懵逼,仔细研究一下,发现是有规律的。
[ti:aLIEz]
[ar:SawanoHiroyuki[nZk]:mizuki]
[al:o1]
[ly:澤野弘之]
[mu:澤野弘之]
[ma:]
[pu:]
[by:ttpod]
[total:268512]
[offset:0]
[00:00.000]<195>aLIEz <199>- <451>SawanoHiroyuki[nZk]:mizuki
[x-trans]彻头彻尾的谎话 - SawanoHiroyuki[nZk]:mizuki
[00:01.095]<201>做<250>詞<200>:<201>澤<200>野<199>弘<300>之
[x-trans]
[00:02.846]<200>做<150>曲<150>:<200>澤<200>野<351>弘<349>之
[x-trans]
[00:20.828]<200>決<250>め<200>つ<201>け<149>ば<201>か<349>り
[x-trans]一直专断专权
[00:23.279]<200>自<200>惚<200>れ<200>を<200>着<400>た
[x-trans]老是自负逞强
[00:24.979]<200>チ<200>ー<200>プ<450>な<550>hokori<350>で
[x-trans]明明只是一文不值的骄傲
......
refactoringLyrics(lyric){
let text = lyric.split('[offset:0]')[1];
let textArr = text.split('\n');
let lyricsArr = [], translate = [];
textArr.forEach((item, index) => {
let time = 0, text = '';
if (item.indexOf('[x-trans]') > -1) {
translate.push(item.split('[x-trans]')[1])
} else if (item.trim() != '') {
time = item.slice(1, 6).split(':');
time = parseInt(time[0]) * 60 + parseInt(time[1]);
text = item.slice(11);
let arr = text.split('>');
let str = arr.reduce((a, b) => {
return a.split('<')[0] + b.split('<')[0]
});
let obj = {
time: time,
text: str
};
lyricsArr.push(obj);
}
});
for (let i in translate) {
lyricsArr[i].text = lyricsArr[i].text + '\n' + translate[i];
}
this.currentLyrics = lyricsArr;
},
复制代码
为了遵循模块化开发,决定将搜索栏写成一个子组件。在同一页面下写子组件,子组件挂载到对应的template就有讲究了。此template不能被父组件的挂载元素包含,不然父组件渲染时会由于没法渲染子组件中的数据而报undefined。
<div id="app" class="main">
...
</div>
<template id="search-box">
...
</template>
var searchBox = {
template: '#search-box',
props: {
isShow: Boolean,
openFun: Function
},
data(){
return {
resultList: [],
searchValue: '',
}
},
methods: {
}
};
new Vue({
el: '#app',
components: {
'com-tip': tip,
'search-box': searchBox
},
...
})
复制代码
经过jsonp去请求数据,须要设置一个callback函数,此callback写成一个全局函数,若是不这样写,而是经过 searchBox.methods.callback的形式,this指向将为methods。而没法直接给searchBox的data赋值。 因而经过eventBus来处理,这样更易维护。
var EventBus = new Vue();
var callBack = function(result) {
console.log(result);
EventBus.$emit('callBack', result);
};
...
mounted(){
let self = this;
EventBus.$on('callBack', function(res) {
if (res && res.data) {
self.resultList = res.data.songs;
}
})
}
...
复制代码
下次再打开,应该播放列表应该保留上一次的数据,这个可直接用localstrong实现
滤镜模糊 http://www.zhangxinxu.com/wordpress/2013/11/css-svg-image-blur/
css图标 www.uiplayground.in/css3-icons/
flex 兼容写法: www.cnblogs.com/iriszhang/p…
flex 布局教程 www.ruanyifeng.com/blog/2015/0…
滑动条样式自定义 blog.csdn.net/u013347241/…
隐藏滚动条兼容 segmentfault.com/q/101000000…
audio属性 developer.mozilla.org/zh-CN/docs/…
audio事件 developer.mozilla.org/zh-CN/docs/…
使用cdn,vue的prop只支持中线格式,驼峰格式不生效
ps: 在用webpack打包的项目中用驼峰是能够,在打包过程当中,会作处理。
// 正确写法
<search-box :is-show="showSearch" :open-fun="openSearch" @push-song="pushNewSong"
@play-song="playSong"></search-box>
// 错误写法
<search-box :isShow="showSearch" :openFun="openSearch" @pushSong="pushNewSong"
@playSong="playSong"></search-box>
复制代码
手动修改进度,偶尔会不生效。
搜索暂不支持分页
不支持建歌单
背景颜色与进度条颜色相近需修改进度条颜色
不支持播放模式选择-单曲循环-随机播放