vue一个页面实现音乐播放器的示例


Posted in Javascript onFebruary 06, 2018

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

效果如下:

vue一个页面实现音乐播放器的示例

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,然后用div来代替。现在是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控制。

<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>??lt;200>野<199>弘<300>之
[x-trans]
[00:02.846]<200>作<150>曲<150>:<200>??lt;200>野<351>弘<349>之
[x-trans]
[00:20.828]<200>?Q<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
  },
  ...
})

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>

待优化

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

搜索暂不支持分页

不支持建歌单

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
获取body标签的两种方法
Oct 13 Javascript
jQuery获得子元素个数的方法
Apr 14 Javascript
JavaScript简单遍历DOM对象所有属性的实现方法
Oct 21 Javascript
实例详解AngularJS实现无限级联动菜单
Jan 15 Javascript
Webpack 服务器端代码打包的示例代码
Sep 19 Javascript
JavaScript框架Angular和React深度对比
Nov 20 Javascript
如何让node运行es6模块文件及其原理详解
Dec 11 Javascript
Layui数据表格跳转到指定页的实现方法
Sep 05 Javascript
浅谈Three.js截图并下载的大坑
Nov 01 Javascript
微信小程序自定义联系人弹窗
May 26 Javascript
js+for循环实现字符串自动转义的代码(把后面的字符替换前面的字符)
Dec 24 Javascript
jquery实现广告上下滚动效果
Mar 04 jQuery
使用百度地图实现地图网格的示例
Feb 06 #Javascript
js中的闭包学习心得
Feb 06 #Javascript
JS基于设计模式中的单例模式(Singleton)实现封装对数据增删改查功能
Feb 06 #Javascript
Vue仿今日头条实例详解
Feb 06 #Javascript
electron demo项目npm install安装失败的解决方法
Feb 06 #Javascript
详解React开发必不可少的eslint配置
Feb 05 #Javascript
详解js的作用域、预解析机制
Feb 05 #Javascript
You might like
PHP MYSQL实现登陆和模糊查询两大功能
2016/02/05 PHP
PHP命令空间namespace及use的用法小结
2017/11/27 PHP
PHP ADODB实现事务处理功能示例
2018/05/25 PHP
php语法检查的方法总结
2019/01/21 PHP
JS通过相同的name进行表格求和代码
2013/08/18 Javascript
node.js中的fs.rmdirSync方法使用说明
2014/12/16 Javascript
JavaScript数据类型判定的总结笔记
2015/07/31 Javascript
onclick和onblur冲突问题的快速解决方法
2016/04/28 Javascript
使用BootStrap建立响应式网页——通栏轮播图(carousel)
2016/12/21 Javascript
node 利用进程通信实现Cluster共享内存
2017/10/27 Javascript
微信小程序获取音频时长与实时获取播放进度问题
2018/08/28 Javascript
vue使用swiper实现中间大两边小的轮播图效果
2019/11/24 Javascript
javascript实现留言板功能
2020/02/08 Javascript
Vue实现点击箭头上下移动效果
2020/06/11 Javascript
js实现弹幕墙效果
2020/12/10 Javascript
Vue 组件注册全解析
2020/12/17 Vue.js
Python使用django获取用户IP地址的方法
2015/05/11 Python
Python通过RabbitMQ服务器实现交换机功能的实例教程
2016/06/29 Python
python实现从文件中读取数据并绘制成 x y 轴图形的方法
2018/10/14 Python
深入了解Python iter() 方法的用法
2019/07/11 Python
详解Python二维数组与三维数组切片的方法
2019/07/18 Python
详解django实现自定义manage命令的扩展
2019/08/13 Python
实现Python与STM32通信方式
2019/12/18 Python
Python嵌套函数,作用域与偏函数用法实例分析
2019/12/26 Python
python实现银行实战系统
2020/02/26 Python
里程积分管理买卖交换平台:Points.com
2017/01/13 全球购物
实习护士自我鉴定
2013/10/13 职场文书
电气工程和自动化自荐信范文
2013/12/25 职场文书
关于廉洁的广播稿
2014/01/30 职场文书
篝火晚会策划方案
2014/05/16 职场文书
竞选班干部演讲稿500字
2014/08/20 职场文书
党的群众路线对照检查材料(个人)
2014/09/24 职场文书
如何撰写促销方案?
2019/07/05 职场文书
python 远程执行命令的详细代码
2022/02/15 Python
vue css 相对路径导入问题级踩坑记录
2022/06/05 Vue.js
python数字图像处理数据类型及颜色空间转换
2022/06/28 Python