最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

JS实现音乐播放器界面

来源:懂视网 责编:小采 时间:2020-11-27 19:58:27
文档

JS实现音乐播放器界面

JS实现音乐播放器界面:这次给大家带来JS实现音乐播放器界面,JS实现音乐播放器界面的注意事项有哪些,下面就是实战案例,一起来看一下。本文介绍了vue一个页面实现音乐播放器的示例,分享给大家,具体如下:效果如下:项目地址:https://github.com/ermu592275254/Mi
推荐度:
导读JS实现音乐播放器界面:这次给大家带来JS实现音乐播放器界面,JS实现音乐播放器界面的注意事项有哪些,下面就是实战案例,一起来看一下。本文介绍了vue一个页面实现音乐播放器的示例,分享给大家,具体如下:效果如下:项目地址:https://github.com/ermu592275254/Mi
这次给大家带来JS实现音乐播放器界面,JS实现音乐播放器界面的注意事项有哪些,下面就是实战案例,一起来看一下。

本文介绍了vue一个页面实现音乐播放器的示例,分享给大家,具体如下:

效果如下:

项目地址:https://github.com/ermu592275254/MiniMusicPlayer

演示地址: https://ermu592275254.github.io/MiniMusicPlayer/(歌曲链接已失效)

开发前构思

界面

做音乐播放器,界面一定要炫酷。太low了听歌没感觉。本身是为了在上班的时候用,于是做成了一个类似网易云音乐的界面,大小合适。不用兼容手机端。

用css做图标

本怀着简单实用的需求去考虑,图标可用SVG、url或者css。相对于url,SVG和css更好一些。为了修炼,最终选择的css。利用好after和before,能减少很多dom嵌套。

.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;
}

画一个唱片

网易云的唱片很好看,我也要弄一个唱片! 用好 box-shadow ,一个元素便可以做成很好看的唱片效果。

.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做进度条

audio本身的样式很难看,并且不同的浏览器呈现出来的效果也不一样。当然你可以修改audio的样式,传统的做法是通过controls属性来隐藏audio,然后用p来代替。现在是html5时代了,当然要用更符合场景的新元素————range。

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);
}

背景滤镜模糊

将图片设置为背景的感觉很棒,可以说整个播放器的颜值这背景提供了一半。设置也非常简单,用到了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控制。

<p class="bg-blur" :style="`background-image:url(${currentSong.album_logo})`"></p>

歌曲资源

爬下接口

直接去虾米官网打开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。

<p id="app" class="main">
...
</p>
<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
 },
 ...
})

eventBus解决数据传输

通过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储存歌曲信息

下次再打开,应该播放列表应该保留上一次的数据,这个可直接用localstrong实现

踩了坑

prop传递数据

使用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>

待优化

手动修改进度,偶尔会不生效。

搜索暂不支持分页

不支持建歌单

背景颜色与进度条颜色相近需修改进度条颜色

不支持播放模式选择-单曲循环-随机播放

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

Express与Koa2的使用详解

地图网格的实现

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

JS实现音乐播放器界面

JS实现音乐播放器界面:这次给大家带来JS实现音乐播放器界面,JS实现音乐播放器界面的注意事项有哪些,下面就是实战案例,一起来看一下。本文介绍了vue一个页面实现音乐播放器的示例,分享给大家,具体如下:效果如下:项目地址:https://github.com/ermu592275254/Mi
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top