# H5网易云 **Repository Path**: ancientelement/h5-netease-cloud ## Basic Information - **Project Name**: H5网易云 - **Description**: 网易云项目 - **Primary Language**: JavaScript - **License**: MPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-10-22 - **Last Updated**: 2023-03-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 1.移动端适配 rem布局 采用类似淘宝flex布局 划分屏幕 js-rem.js ```js function remSize() { //获取设备宽度 var deciceWidth = document.documentElement.clientWidth || window.innerWidth; console.log(deciceWidth); if (deciceWidth >= 750) { deciceWidth = 750 } if (deciceWidth <= 320) { deciceWidth = 320 } // 750px --> 1rem = 100px ,375px --> 1rem = 50px document.documentElement.style.fontSize = (deciceWidth / 7.5) + 'px' //设置字体大小 document.querySelector('body').style.fontSize = 0.3 + 'rem' } remSize(); window.onresize = function () { //窗口发生变化 remSize(); } ``` ### 2.使用vant组件库 一个移动端的 UI 弹出窗口 swiper ### 3. 项目难点 vuex 底部歌曲的全局状态管理 其中 我们最常用 的是歌曲播放状态 和歌曲列表 ```js import { createStore } from 'vuex' export default createStore({ state: { playList: [{ //播发列表 al: { id: 35139, name: "追梦痴子心", pic: 19061133579343590, picUrl: "https://p1.music.126.net/XDncptlBJ4_LN3hLBx-8aw==/19061133579343591.jpg", pic_str: "19061133579343591", }, ar: [{ name: "GALA" }], name: "追梦赤子心", id: 355992, }], playListIndex: 0, // 当前播放的歌曲 isPlay: false,//是否在播放 detailShow: false, //详情页展示 }, getters: { }, mutations: { UPDATEISPLAY(state, value) { state.isPlay = value }, UPDATAEPLAYLIST(state, value) { state.playList = value }, UPDATEPLAYLISTINDEX(state, value) { state.playListIndex = value }, UPDATEDETAILSHOW(state, value) { state.detailShow = !state.detailShow } }, actions: { }, modules: { } }) ``` #### 3.1 animation 奇怪的地方 为什么直接给 pic 加 animation: rotate 10s linear infinite 就会使得 animation-play-state: running 和pause 失效 而 将其放在 go 里 在将 go 加在图片上就 不会失效 ```less .detial-content { width: 100%; height: 8.6rem; .go { //匀速 循环 animation: rotate 10s linear infinite; } .rotate_active { animation-play-state: running; } .rotate_pause { animation-play-state: paused; } @keyframes rotate { 0% { transform: rotateZ(0deg); } 100% { transform: rotateZ(360deg); } } .pic { width: 3.06rem; height: 3.06rem; border-radius: 50%; position: absolute; margin: 0 auto; left: 30%; top: 28.3%; } } ``` ### 4.歌词处理 我们用split() 加正则表达式的方法 \r\n 换行回车 匹配和切割歌词 ```js lyricNew() { let arr = this.lyric.lyric.split(/[(\r\n)\r\n]+/).map((item, i) => { let min = item.slice(1, 3); let second = item.slice(4, 6); let ms = item.slice(7, 10); let lrc = item.slice(11, item.length); if (isNaN(Number(ms))) { ms = item.slice(7, 9); lrc = item.slice(10, item.length); } // console.log(min, second, ms, lrc); return { min, second, ms, lrc }; }); return arr; }, ``` ```css //记住这两个属性处理滚动很重要 overflow: hidden; overflow: scroll; ``` #### 4.1时间与歌词相联系 通过 audio 的currentTime(当前播放时间) 和 duration (歌曲全部时间) audio的 timeupdate 事件可以监视歌曲事件的改变 ```js currentTime() { const audio = this.$refs.audio; audio.addEventListener("timeupdate", () => { console.log(111, audio.currentTime); this.UPDATECURRENTTIME(audio.currentTime); }); }, ``` #### 4.2正在播放的歌词高亮 主要是获取正在播放的行的时间区间 ```js computed: { ...mapState(["lyric", "currentTime", "duration"]), //对歌词进行切割 lyricNew() { let arr = this.lyric.lyric.split(/[(\r\n)\r\n]+/).map((item, i) => { let min = item.slice(1, 3); let second = item.slice(4, 6); let ms = item.slice(7, 10); let lrc = item.slice(11, item.length); let time = parseInt(min) * 60 + parseInt(second); if (isNaN(Number(ms))) { ms = item.slice(7, 9); lrc = item.slice(10, item.length); } // console.log(min, second, ms, lrc); return { min, second, ms, lrc, time }; }); // 最后还有一个多余 元素为空 会影响 time 的值我们删去他 arr.splice(arr.length - 2, arr.length - 1); // 给每行歌词元素添加 下一行时间 arr.forEach((item, i) => { if (i === arr.length - 1) { item.nextTime = this.duration; } else { item.nextTime = arr[i + 1].time; } }); return arr; }, }, ``` ##### 4.2.1 关键的一步 将当前 相应时间 歌词 与 播放时间联动 active 当前播放歌词的样式 ```html
{{ item.lrc }}
``` #### 4.3 跟随滚动 这里操作了dom 做实不该 \ 我们给歌词的父级加上ref 用于获取滚动的属性 scrollTop 距离顶部的滚动距离 ```html