Skip to content

🎵帅气的手机端音乐播放器(vue vue-router vuex flex ...)

License

Notifications You must be signed in to change notification settings

hzzly/MagicMusic

Repository files navigation

MagicMusic

前言:在最近的一个外包项目中包联盟中使用到了video,遇到了好多坑。突发奇想来踩一踩audio的坑😀,果然一入深似海,👇下面将分享我的DIY之路-Vue音乐播放器。 注:本项目为开源项目,不能用于商业应用,仅供学习。

[温馨提示:pc浏览f12手机模式最佳,手机建议wifi下访问]

demo地址: http://hzzly.net/magic-music 欢迎大家的star啦😄~

Build Setup

# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report

API

$ git clone [email protected]:Binaryify/NeteaseCloudMusicApi.git
$ npm install
$ node app.js

跨域

在 clone 下来的api中的 app.js 中添加如下代码(这是API中的app.js,不是项目中的,好多人说找不到!!!)

//设置跨域访问  
app.all('*', function(req, res, next) {  
    res.header("Access-Control-Allow-Origin", "*");  
    res.header("Access-Control-Allow-Headers", "X-Requested-With");  
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");  
    res.header("X-Powered-By",' 3.2.1')  
    res.header("Content-Type", "application/json;charset=utf-8");  
    next();  
});  

👉老铁们,准备发车(技能点):

👉坐好,出发

实现的功能

1、首页

  • 轮播
  • 个性推荐[流行、古典、轻音乐、流行]
  • 歌曲操作
    • 加入播放列表
    • 喜欢
    • 分享

2、底部播放控件

  • 播放
  • 暂停
  • 下一曲
  • 播放进度条

3、播放页面

  • 上一曲
  • 播放
  • 暂停
  • 下一曲
  • 播放进度条[弧形进度条]
  • 歌词滚动
  • 播放的歌词高亮
  • 播放模式[单曲循环、列表循环、随机播放]

4、播放列表

  • 播放歌曲高亮
  • 切歌(单击切歌)
  • 删歌(点击右侧小X)
  • 清空播放列表
  • 本地缓存播放列表

5、排行榜

  • 热门排行榜
  • 排行榜里的歌曲(单击播放)

6、音乐搜索

输入搜索关键词,点击放大镜图标

  • 单曲(单击或点击歌曲操作(...)添加至音乐播放列表,部分音乐会存在版权问题无法播放)
  • 歌手
  • 专辑
  • 歌单
  • 用户

侧边栏

  • 头像
  • 菜单
    • 个人中心

API

感谢作者把api整理的这么好(点个赞👍)

网易云音乐 NodeJS 版 API

开发心得与总结

1、轮播图

首先感谢作者ShanaMaid/vue-image-scroll开源的代码,我把代码copy下来自己进行了一点修改(没有手指滑动效果),因为这是移动端,少不了的手指滑动切换,所以添加了vue-touch(偷偷告诉你,vue-touch的next分支还是支持vue2.0的😜)。代码传送门

<li v-for="(item,index) in image" :class="[move[index]]">
    <v-touch class="vuetouch"
            v-on:swipeleft="nextPic"
            v-on:swiperight="prePic">
        ...
    </v-touch>
</li>

methods: {
    nextPic(event) {
        let temp = this.move.pop()
        this.move.unshift(temp)
    },
    prePic(event) {
        let temp = this.move.shift()
        this.move.push(temp)
    },
}

2、歌曲操作(喜欢,分享,加入播放列表)动画、播放列表展开与删除歌曲动画

Vue提供了transition的封装组件,在下列情形中,可以给任何元素和组件添加 entering/leaving 过渡

  • 条件渲染 (使用 v-if)
  • 条件展示 (使用 v-show)
  • 动态组件
  • 组件根节点
<transition name="move">
    <div class="menu" v-show="item.menuShow">
        ...
    </div>
</transition>

<transition-group name="slide" tag="div" class="list-wrapper">
    <div class="item" v-for="(item, index) in listenLists" :key="item">
        ...
    </div>
</transition-group>

transition-group一组过度动画,这里有个小坑的,之前看官网列表过渡的栗子,给每一项设置唯一的key值,一般都会用index。所以在做的时候就把index传给key,结果过渡老是不对,后来换成对应的item就正常了(生无可恋脸)。

3、直线进度条、弧形进度条

西班牙建筑大师曾说过:“直线属于人类,曲线则归于上帝”。在这里我大胆的使用了弧形来作为进度条,(几大热门音乐APP貌似还没有弧形进度条😄)。

这里我用到了Vue的绑定内联样式

//首页底部直线进度条
<div class="progress-bar">
    <div class="play"
        :style="{width: (now / duration).toFixed(3)*100 + '%'}"></div>
</div>

//播放页弧形进度条
//因为用到了弧形,所以我这里用到了`border-radius`来使它变成一个大圆,然后平移`translateX`居中,其它不要的部分`overflow: hidden`。
//这里用两个div来表示进度条,一条固定的进度条,一条慢慢增加。
<div class="process" @click="showToast">
    <div class="line"></div>
    <div class="pro" :style="{transform: `translateX(${translateX}) rotate(${deg*1 + 56.5*((now / size).toFixed(3))}deg)`}"></div>
</div>

4、本地存储

将一些数据缓存到localStorage,可以减少Http请求,从而优化页面加载时间。

在这个项目中首页歌曲列表以及搜索历史用到了本地缓存,拿搜索历史来举栗:

created() {
    if (!localStorage.searchHistory) {
        let searchHistory = ['前端', '童话镇', '刚好遇见你']
        localStorage.searchHistory = JSON.stringify(searchHistory)
    } 
},
methods: {
    _search(keywords) {
        //判断搜索列表中是否已存在
        let searchHistory = JSON.parse(localStorage.searchHistory)
        let find = searchHistory.findIndex((val) => {
            return val === keywords
        })
        find === -1 ? localStorage.searchHistory = JSON.stringify([keywords, ...searchHistory]) : ''
    }
}

5、图片懒加载

使用了vue-lazyload插件 用法👉:

$ npm install vue-lazyload
//main.js
import VueLazyLoad from 'vue-lazyload'
import def_lazy_img from '../static/img/loading.gif' //懒加载的默认图片
Vue.use(VueLazyLoad,{
    loading: def_lazy_img
}) //使用懒加载组件

//在使用img标签的地方使用
<img v-lazy="item.al.picUrl" alt="">

6、歌词滚动与高亮

因为api提供的歌词包括时间,如:[03:57.280]原谅我这一生不羁放纵爱自由 所以首先要进行字符串切割:

<div class="lyric">
    <div class="roll-lyric" v-html="lyrics" ref="lyric"></div>
</div>

computed: {
    lyrics() {
        let lyrics = ''
        this.lyricArr = []
        if (this.lyric) {
            let arr = this.lyric.split('\n')
            for (let item of arr) {
                if (item) {
                    let arr2 = item.split(']')
                    this.lyricArr.push(arr2[0].substring(1,3)*60+arr2[0].substring(4)*1)
                    if (arr2) {
                        lyrics += `<p class='lyrichook' style='margin: 10px 0'>${arr2[1]}</p>`
                    }
                }
            }
        } else {
            lyrics = '暂无歌词~'
        }
        return lyrics
    }
}

然后在播放的监听事件中与播放的当前做对比:

this.$refs.myAudio.addEventListener('play', () => {
    this.pDOM = [...document.querySelectorAll('.lyrichook')]
    timer = setInterval(() => {
        this.now = audioDOM.currentTime
        this.lyricArr.forEach((item, index) => {
            if (parseInt(item) == parseInt(this.now)) {
                this.pDOM.forEach((p) => {
                    p.style.color = 'rgba(255,255,255,.8)' //其它歌词清除高亮
                });
                this.pDOM[index].style.color = '#f12c61' //歌词高亮
                this.$refs.lyric.style.transform = `translateY(-${(index-2)*25}px)` //歌词滚动
            } 
        });
    }, 1000)
})

到这就ok了😜

7、vuex状态管理

推荐官方调试工具 devtools extension

想进一步理解vuex,可以看这篇博客vuex学习实践笔记

之前看到好多人写的vuex,把整个项目的数据放到了一个state里,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。

所以我建议(个人见解,轻喷):将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters。这样方便管理与后期的维护。

车已到站✌️。

不知不觉写了这么多,老铁们凑合这看吧😁,觉得还行的可以点个star,你的star是我继续开源创作的动力,谢谢!!!

About

🎵帅气的手机端音乐播放器(vue vue-router vuex flex ...)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published