html背景模糊的音乐播放器,vue移动端仿音乐播放器

本文详细介绍了如何模仿QQ音乐构建一个带有歌词滚动、动画唱片旋转及拖拽进度控制的音乐播放器。通过固定背景、Swiper组件、音频控制和触摸交互实现无缝体验。关键点包括定时器监听、拖拽事件处理和播放控制逻辑。
摘要由CSDN通过智能技术生成

工作之余查了很多资料一步步摸索出来的,先感谢各位大佬。

仿QQ音乐做的,不是100%还原,不过基本原理都在这了,结合之前的歌词滚动组件一起使用

持续更新

效果图

e51f9718af9a

专辑+歌词播放

e51f9718af9a

纯歌词播放

页面布局拆分

总体分为

1顶部歌名+歌手的top-bar模块+模糊背景

2专辑+歌词滚动模块

3进度条+时间模块

4播放控件模块,播放,暂停,上一曲,下一曲。

需要注意音频初始化audioInit

mounted() {

const audio = document.getElementById("audio");

this.init();

this.audioInit();

this.swiper = new Swiper(this.activeClass, {

autoplay: false, //自动播放

loop: false, //循环播放

});

},

method: {

audioInit() {

let that = this;

// 音频或视频文件已经就绪可以开始

audio.addEventListener("canplay", () => {

console.log("canplay");

that.audioDuration = that.TimeToString(audio.duration);

let buffered = audio.buffered.end(0)

});

let progressL = this.$refs.track.offsetWidth; // 进度条总长

audio.addEventListener("timeupdate", () => {

// 当前播放时间

let compareTime = audio.currentTime;

let buffered = audio.buffered.end(0)

for (let i = 0; i < that.lyricInfo.length; i++) {

if (compareTime > parseInt(that.lyricInfo[i].time)) {

const index = that.lyricInfo[i].index;

if (i === parseInt(index)) {

that.lyricIndex = i; //获取当前播放歌曲的歌词index

}

}

}

that.currentTime = that.TimeToString(audio.currentTime);

that.audioPercent =

audio.currentTime / audio.duration.toFixed(3);

that.thumbTranslateX = that.audioPercent * 4;

});

audio.addEventListener("ended", () => {

that.playIndex =

that.playIndex + 1 >= that.songList.length

? 0

: that.playIndex + 1;

that.songInfo = that.songList[that.playIndex];

that.GetLyric(that.songInfo.id);

setTimeout(() => {

audio.play();

}, 100);

});

},

}

第一部分

需要定一个固定在页面的div,采用fixed布局

class="background-flitter"

:style="`background-image: url(${songInfo.cover})`"

>

{{ songInfo.name }}

{{ songInfo.artistsName }}

具体的歌曲信息如下

data: (){

return {

{

albumId: 93162249,

albumTitle: "STRAY SHEEP",

artistsName: "米津玄師",

cover:"https://p1.music.126.net/6mhlWCOOQkT0xDjjuCLW7g==/109951165181187586.jpg",

id: 1466598056,

index: 7,

name: "Lemon",

url:"https://music.163.com/song/media/outer/url?id=1466598056.mp3",

},

}

}

.main-page {

width: 100%;

height: 100vh;

position: relative;

background: rgba(15, 15, 15, 0.3);

.background-flitter {

position: fixed;

z-index: -2;

background-repeat: no-repeat;

width: 100%;

height: 100vh;

top: 0;

left: 0;

background-size: cover;

background-position: 50%;

filter: blur(0.16rem);

opacity: 0.7;

overflow: hidden;

box-sizing: border-box;

}

.top-bar {

width: 100%;

height: 1.2rem;

text-align: center;

color: #fff;

font-size: 0.32rem;

line-height: 0.6rem;

font-weight: 600;

}

}

至此完成整体背景和top-bar部分

第二部分,专辑+歌词滚动

左右滑动切换用到了swiper组件,专辑+歌词和纯歌词分别放在两个slide就可以了。

先固定一个歌词容器,与top-bar同级,具体代码可以参考歌词组件封装来看,都是复用的代码。

//ref="rotate"

v-for="(item, index) in lyricInfo"

:key="index"

:style="{

color:

lyricIndex === index

? colorLight

: color,

}"

>

{{ item.lyric }}

ref="lyric"

:color="color"

:colorLight="colorLight"

:lineHeight="lineHeight"

:paddingTop="paddingTop"

:fontSize="fontSize"

:lyricIndex="lyricIndex"

:lyricsList="lyricInfo"

>

歌词滚动之前文章有讲过了,提一下这个唱片旋转的动画吧,给旋转部分添加ref="rotate"

.disc {

width: 5rem;

height: 5rem;

border-radius: 50%;

box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 0.4);

animation: animations1 12s linear infinite forwards;

animation-play-state: paused;

overflow: hidden;

img {

width: 100%;

height: 100%;

}

}

@keyframes animations1 {

from {

transform: rotate(0deg);

}

to {

transform: rotate(360deg);

}

}

在播放事件中添加

//播放与暂停

play() {

if (this.playing) {

// 播放中,点击则为暂停

this.playing = false;

this.$refs.rotate.style.animationPlayState = "paused";

audio.pause();

} else {

// 暂停中,点击则为播放

this.playing = true;

this.$refs.rotate.style.animationPlayState = "running";

audio.play();

}

},

到这完成了歌词滚动和切换

第三部分,进度条点击和拖拽控制播放进度(重点)

样式,时长比这些都讲烂了,讲讲点击和拖拽控制播放进度吧

拖拽功能:给拖拽按钮,也就是示例图的白色进度按钮添加三个事件

class="play-point"

@touchstart.stop.prevent="touchstart"

@touchmove.stop.prevent="touchmove"

@touchend.stop.prevent="touchend"

:style="{

transform: 'translateX(' + thumbTranslateX + 'rem)',

}"

>

//控制播放进度

SetProgress(t) {

audio.currentTime = audio.duration * t;

},

touchstart(event) {

let progressL = this.$refs.track.offsetWidth ; // 进度条总长

let allL = this.$refs.MainRef.offsetWidth ; // 页面总长

let half = (allL-progressL)/2

console.log("开始", progressL, allL, half)

//记录开始的X轴坐标

if (this.startXFirst) {

this.startX = half;

this.startXFirst = false;

}

},

touchmove(event) {

let moveX = parseInt(

(event.changedTouches[0].clientX - this.startX)

);

let progressL = this.$refs.track.offsetWidth; // 进度条总长

let percent = (moveX / progressL).toFixed(2); //拖动%比

if(percent>1){

percent = 1

}

this.audioPercent = percent; //音频播放%

this.thumbTranslateX = this.audioPercent * 4; //计算滑块位移

},

touchend(event) {

console.log("结束",event)

this.finalX = parseInt(

event.changedTouches[0].clientX - this.startX

);

let progressL = this.$refs.track.offsetWidth; // 进度条总长

let time = (this.finalX / progressL).toFixed(2);

if(time>1){

time = 1

}

this.SetProgress(time);

},

点击实现进度则简单多了,

class="progress"

@click="HandleProgressClick($event)"

ref="track"

>

class="progress_box"

:style="{ width: audioProgressPercent }"

>

class="play-point"

@touchstart.stop.prevent="touchstart"

@touchmove.stop.prevent="touchmove"

@touchend.stop.prevent="touchend"

:style="{

transform: 'translateX(' + thumbTranslateX + 'rem)',

}"

>

//点击进度条

HandleProgressClick(event) {

let progressL = this.$refs.track.offsetWidth; // 进度条总长

let clickX = event.offsetX;

let time = (clickX / progressL).toFixed(2);

this.SetProgress(time);

},

OK ,第三部分完成

第四部分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值