refactor(播放器): 优化音频播放逻辑和学生切换功能
- 重构音频播放管理逻辑,简化播放状态控制 - 改进学生切换功能,使用索引代替顺序号 - 移除冗余代码,优化音量控制实现 - 调整CSS布局样式,增强页面展示效果
This commit is contained in:
14
index.html
14
index.html
@@ -57,7 +57,7 @@
|
|||||||
<img class="bj bj1" src="./static/img/album-bj1.svg" />
|
<img class="bj bj1" src="./static/img/album-bj1.svg" />
|
||||||
<img class="bj bj2" src="./static/img/album-bj2.svg" />
|
<img class="bj bj2" src="./static/img/album-bj2.svg" />
|
||||||
<div class="album-box" ref="albumBoxRef">
|
<div class="album-box" ref="albumBoxRef">
|
||||||
<div class="item" v-for="(item, index) in bannerList" :key="index" @click="openPreview(item.id, item.img)">
|
<div class="item" v-for="(item, index) in bannerList" :key="index" @click="openPreview(item.id)">
|
||||||
<img class="img" :src="item.img" />
|
<img class="img" :src="item.img" />
|
||||||
<img class="bj bj3" src="./static/img/album-bj3.svg" />
|
<img class="bj bj3" src="./static/img/album-bj3.svg" />
|
||||||
<img class="bj bj4" src="./static/img/album-bj4.png" />
|
<img class="bj bj4" src="./static/img/album-bj4.png" />
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="trait flexflex mar1200">
|
<div class="trait flexflex mar1200">
|
||||||
<div class="item flexflex flex1" v-for="(item, index) in trait" :key="index">
|
<div class="item flexflex" v-for="(item, index) in trait" :key="index">
|
||||||
<img class="icon" :src="item.icon" />
|
<img class="icon" :src="item.icon" />
|
||||||
<div class="title">{{ item.title }}</div>
|
<div class="title">{{ item.title }}</div>
|
||||||
<div class="text">{{ item.text }}</div>
|
<div class="text">{{ item.text }}</div>
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
<div class="time">{{ item.date }}</div>
|
<div class="time">{{ item.date }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="media" @click="openPreview(item.id, item.img)">
|
<div class="media" @click="openPreview(item.id)">
|
||||||
<img class="img" :src="item.img" />
|
<img class="img" :src="item.img" />
|
||||||
<img class="play" src="./static/img/play-white-icon.svg" />
|
<img class="play" src="./static/img/play-white-icon.svg" />
|
||||||
</div>
|
</div>
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
<div class="name">{{ item.title }}</div>
|
<div class="name">{{ item.title }}</div>
|
||||||
<div class="subtitle">{{ item.desc }}</div>
|
<div class="subtitle">{{ item.desc }}</div>
|
||||||
<div class="time">{{ item.date }}</div>
|
<div class="time">{{ item.date }}</div>
|
||||||
<div class="progress-bar flexacenter">
|
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
|
||||||
<div class="bar white" :style="{ width: item.progress + '%' }"></div>
|
<div class="bar white" :style="{ width: item.progress + '%' }"></div>
|
||||||
<div class="bar black flex1"></div>
|
<div class="bar black flex1"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
<div class="info flexflex">
|
<div class="info flexflex">
|
||||||
<div class="name">{{ item.title }}</div>
|
<div class="name">{{ item.title }}</div>
|
||||||
<div class="lyric">{{ item.desc }}</div>
|
<div class="lyric">{{ item.desc }}</div>
|
||||||
<div class="progress-bar flexacenter">
|
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
|
||||||
<div class="bar white" :style="{ width: item.progress + '%' }"></div>
|
<div class="bar white" :style="{ width: item.progress + '%' }"></div>
|
||||||
<div class="bar black flex1"></div>
|
<div class="bar black flex1"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
<div class="student-box flexflex">
|
<div class="student-box flexflex">
|
||||||
<img class="title" src="./static/img/student-title.png" alt="" />
|
<img class="title" src="./static/img/student-title.png" alt="" />
|
||||||
<div class="list flexacenter">
|
<div class="list flexacenter">
|
||||||
<img class="img" :class="[`img${ item.order }`]" v-for="(item, index) in studentList" :src="item.img" :key="index" @click="cutStudent(item.order)" />
|
<img class="img" :class="[`img${ item.order }`]" v-for="(item, index) in studentList" :src="item.img" :key="index" @click="cutStudent(index, item.order)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="name">《{{ zeroOrderStudents.title }}》</div>
|
<div class="name">《{{ zeroOrderStudents.title }}》</div>
|
||||||
<div class="info flexacenter">
|
<div class="info flexacenter">
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
{{ zeroOrderStudents.name }} | {{ zeroOrderStudents.age }}岁 | {{ zeroOrderStudents.city }}
|
{{ zeroOrderStudents.name }} | {{ zeroOrderStudents.age }}岁 | {{ zeroOrderStudents.city }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress-bar flexacenter">
|
<div class="progress-bar flexacenter" @click="handleBarDragBottomClick">
|
||||||
<div class="bar white" :style="{ width: zeroOrderStudents.progress + '%' }"></div>
|
<div class="bar white" :style="{ width: zeroOrderStudents.progress + '%' }"></div>
|
||||||
<div class="bar black flex1"></div>
|
<div class="bar black flex1"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -224,6 +224,7 @@
|
|||||||
.content .introduce .trait {
|
.content .introduce .trait {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
height: 420px;
|
height: 420px;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.content .introduce .trait .item {
|
.content .introduce .trait .item {
|
||||||
padding-top: 98px;
|
padding-top: 98px;
|
||||||
@@ -244,7 +245,7 @@
|
|||||||
margin-bottom: 42px;
|
margin-bottom: 42px;
|
||||||
}
|
}
|
||||||
.content .introduce .trait .item .text {
|
.content .introduce .trait .item .text {
|
||||||
width: 266px;
|
width: 270px;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@
|
|||||||
.trait {
|
.trait {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
height: 420px;
|
height: 420px;
|
||||||
|
justify-content: space-between;
|
||||||
.item {
|
.item {
|
||||||
padding-top: 98px;
|
padding-top: 98px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -276,7 +276,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
width: 266px;
|
width: 270px;
|
||||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ const search = createApp({
|
|||||||
if (item.playurl == src) item.progress = val;
|
if (item.playurl == src) item.progress = val;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (zeroOrderStudents.value?.playurl == src) zeroOrderStudents.value["progress"] = val;
|
if (zeroOrderStudents.value?.playurl == src) {
|
||||||
|
zeroOrderStudents.value["progress"] = val;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const introduceRef = ref(null);
|
const introduceRef = ref(null);
|
||||||
@@ -108,6 +110,7 @@ const search = createApp({
|
|||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
ajax("https://pujianchaoyin.com/api/getHomeData").then((res) => {
|
ajax("https://pujianchaoyin.com/api/getHomeData").then((res) => {
|
||||||
|
// ajax("https://pujianchaoyin.com/index/api").then((res) => {
|
||||||
if (res.code != 200) return;
|
if (res.code != 200) return;
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
console.log("data", data);
|
console.log("data", data);
|
||||||
@@ -136,7 +139,9 @@ const search = createApp({
|
|||||||
};
|
};
|
||||||
|
|
||||||
let bannerSwiperTimer = null;
|
let bannerSwiperTimer = null;
|
||||||
|
// 头部轮播图 定时器
|
||||||
const bannerSwiper = () => {
|
const bannerSwiper = () => {
|
||||||
|
clearTimeout(bannerSwiperTimer);
|
||||||
bannerSwiperTimer = setTimeout(() => {
|
bannerSwiperTimer = setTimeout(() => {
|
||||||
let index = pointerIndex.value + 1;
|
let index = pointerIndex.value + 1;
|
||||||
if (index > bannerList.value.length - 1) index = 0;
|
if (index > bannerList.value.length - 1) index = 0;
|
||||||
@@ -145,6 +150,7 @@ const search = createApp({
|
|||||||
}, 3000);
|
}, 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 头部轮播图 - 切换 定时器
|
||||||
const changeInterval = (type) => {
|
const changeInterval = (type) => {
|
||||||
if (type) clearTimeout(bannerSwiperTimer);
|
if (type) clearTimeout(bannerSwiperTimer);
|
||||||
else bannerSwiper();
|
else bannerSwiper();
|
||||||
@@ -172,7 +178,7 @@ const search = createApp({
|
|||||||
|
|
||||||
let art = null;
|
let art = null;
|
||||||
// 开启播放 MV
|
// 开启播放 MV
|
||||||
const openPreview = (id, poster = "") => {
|
const openPreview = (id) => {
|
||||||
ajax("https://pujianchaoyin.com/api/getMvDetail", {
|
ajax("https://pujianchaoyin.com/api/getMvDetail", {
|
||||||
id,
|
id,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
@@ -180,12 +186,13 @@ const search = createApp({
|
|||||||
const data = res.data;
|
const data = res.data;
|
||||||
|
|
||||||
previewState.value = true;
|
previewState.value = true;
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
art = new Artplayer({
|
art = new Artplayer({
|
||||||
container: ".artplayer-app",
|
container: ".artplayer-app",
|
||||||
url: data.playurl,
|
url: data.playurl,
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
poster,
|
poster: data.img || "",
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
});
|
});
|
||||||
art.play();
|
art.play();
|
||||||
@@ -220,13 +227,16 @@ const search = createApp({
|
|||||||
getProgress();
|
getProgress();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 播放 组件数据
|
||||||
let playData = ref(null);
|
let playData = ref(null);
|
||||||
|
|
||||||
|
// 管理音频播放
|
||||||
const manageAudio = (src, area) => {
|
const manageAudio = (src, area) => {
|
||||||
const audio = audioPlayer.value;
|
const audio = audioPlayer.value;
|
||||||
closeAll();
|
closeAll();
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (audio?.src != src) audio.src = src;
|
if (audio?.src != src) audio.src = src;
|
||||||
|
console.log("audio", audio);
|
||||||
|
|
||||||
audio.play().then(() => {
|
audio.play().then(() => {
|
||||||
if (area == "works") {
|
if (area == "works") {
|
||||||
@@ -262,6 +272,7 @@ const search = createApp({
|
|||||||
manageAudio(playurl, area);
|
manageAudio(playurl, area);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 关闭所有播放
|
||||||
const closeAll = () => {
|
const closeAll = () => {
|
||||||
audioPlayer.value.pause();
|
audioPlayer.value.pause();
|
||||||
|
|
||||||
@@ -275,46 +286,44 @@ const search = createApp({
|
|||||||
|
|
||||||
zeroOrderStudents.value["state"] = false;
|
zeroOrderStudents.value["state"] = false;
|
||||||
|
|
||||||
console.log("playData", playData);
|
|
||||||
|
|
||||||
playData.value && (playData.value.state = false);
|
playData.value && (playData.value.state = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 定制音乐 数据
|
||||||
let customList = ref([]);
|
let customList = ref([]);
|
||||||
|
|
||||||
let studentIndex = ref(0);
|
let studentList = ref([]); // 学生数据
|
||||||
let zeroOrderStudents = ref({});
|
let studentIndex = ref(0); // 学生下标
|
||||||
|
let zeroOrderStudents = ref({}); // 学生 选中播放 数据
|
||||||
|
|
||||||
let studentList = ref([]);
|
// 切换学生 播放
|
||||||
|
const cutStudent = (index) => {
|
||||||
const cutStudent = (order) => {
|
|
||||||
// 找到目标元素和第一个元素
|
// 找到目标元素和第一个元素
|
||||||
const [target, first] = [studentList.value.find((item) => item.order == order), studentList.value.find((item) => item.order == 0)];
|
const [target, first] = [studentList.value[index], studentList.value.find((item) => item.order == 0)];
|
||||||
// 交换order值
|
// 交换order值
|
||||||
if (target && first && target !== first) [target.order, first.order] = [first.order, target.order];
|
if (target && first && target !== first) [target.order, first.order] = [first.order, target.order];
|
||||||
|
|
||||||
console.log("studentList.value", studentList.value);
|
|
||||||
|
|
||||||
zeroOrderStudents.value = target;
|
zeroOrderStudents.value = target;
|
||||||
|
studentIndex.value = index;
|
||||||
target.playurl ? manageAudio(target.playurl, "student") : getPlayUrl(0, "student");
|
target.playurl ? manageAudio(target.playurl, "student") : getPlayUrl(0, "student");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 响应式数据:音量值、是否静音
|
// 切换学生 歌曲 上\下一首
|
||||||
const volume = ref(84);
|
const cutSong = (type) => {
|
||||||
const isMuted = ref(false);
|
const listLength = studentList.value.length;
|
||||||
|
const index = studentIndex.value;
|
||||||
|
let newIndex = 0;
|
||||||
|
|
||||||
// 切换静音状态的方法
|
if (type === "up") newIndex = index - 1 < 0 ? listLength - 1 : index - 1;
|
||||||
const toggleMute = () => {
|
else if (type === "down") newIndex = index + 1 >= listLength ? 0 : index + 1;
|
||||||
isMuted.value = !isMuted.value;
|
cutStudent(newIndex);
|
||||||
if (audioPlayer.value) {
|
|
||||||
audioPlayer.value.muted = isMuted.value;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 响应式数据:音量值、是否静音
|
||||||
|
let volume = ref(100);
|
||||||
|
|
||||||
// 计算并设置音量百分比
|
// 计算并设置音量百分比
|
||||||
const setVolumePercentage = (percentage) => {
|
const setVolumePercentage = (percentage) => {
|
||||||
// 确保百分比在0-100之间
|
|
||||||
const volumePercent = Math.max(0, Math.min(100, percentage));
|
const volumePercent = Math.max(0, Math.min(100, percentage));
|
||||||
volume.value = Math.abs(~~volumePercent);
|
volume.value = Math.abs(~~volumePercent);
|
||||||
|
|
||||||
@@ -328,11 +337,8 @@ const search = createApp({
|
|||||||
const progressBar = event.currentTarget;
|
const progressBar = event.currentTarget;
|
||||||
const rect = progressBar.getBoundingClientRect();
|
const rect = progressBar.getBoundingClientRect();
|
||||||
|
|
||||||
// 计算点击位置相对于进度条的比例
|
|
||||||
// 因为是垂直进度条,所以用clientY
|
|
||||||
const clickPosition = rect.bottom - event.clientY;
|
const clickPosition = rect.bottom - event.clientY;
|
||||||
const percentage = (clickPosition / rect.height) * 100;
|
const percentage = (clickPosition / rect.height) * 100;
|
||||||
console.log("percentage", percentage);
|
|
||||||
|
|
||||||
setVolumePercentage(percentage);
|
setVolumePercentage(percentage);
|
||||||
};
|
};
|
||||||
@@ -436,6 +442,7 @@ const search = createApp({
|
|||||||
document.removeEventListener("mouseup", stopBarDragBottom);
|
document.removeEventListener("mouseup", stopBarDragBottom);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 直接点击进度条 跳转
|
||||||
const handleBarDragBottomClick = (event) => {
|
const handleBarDragBottomClick = (event) => {
|
||||||
// 获取进度条元素
|
// 获取进度条元素
|
||||||
const progressBar = event.currentTarget;
|
const progressBar = event.currentTarget;
|
||||||
@@ -476,11 +483,9 @@ const search = createApp({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getPlayUrl = (index, area) => {
|
const getPlayUrl = (index, area) => {
|
||||||
console.log("index", index);
|
|
||||||
let id = null;
|
let id = null;
|
||||||
if (area == "student") {
|
if (area == "student") {
|
||||||
const item = zeroOrderStudents.value;
|
const item = zeroOrderStudents.value;
|
||||||
console.log("item", item.id);
|
|
||||||
id = item.id;
|
id = item.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,31 +494,14 @@ const search = createApp({
|
|||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code != 200) return;
|
if (res.code != 200) return;
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
console.log("data", data);
|
if (area == "student") {
|
||||||
|
|
||||||
zeroOrderStudents.value = { ...data, ...zeroOrderStudents.value };
|
zeroOrderStudents.value = { ...data, ...zeroOrderStudents.value };
|
||||||
|
|
||||||
manageAudio(data.playurl, area);
|
manageAudio(data.playurl, area);
|
||||||
|
|
||||||
console.log(zeroOrderStudents.value, "zeroOrderStudents");
|
console.log(zeroOrderStudents.value, "zeroOrderStudents");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const cutSong = (type, order) => {
|
return { cutSong, getPlayUrl, handleBarDragBottomClick, startBarDragBottom, volumeShow, handleVolumeHide, handleVolumeShow, zeroOrderStudents, rePlay, playData, awardAudioList, changeInterval, awardMVList, bannerList, albumBoxRef, volume, handleVolumeClick, handleVolumeDrag, startDrag, stopDrag, volume, cutStudent, studentList, studentIndex, scrollToPrevious, scrollToNext, changePointer, pointerIndex, visibleRef, studentRef, customRef, formatTime, currentTimeFormatted, durationFormatted, worksRef, introduceRef, customList, closeAll, manageAudio, progress, closePreview, openPreview, previewState, audioPlayer, trait, fastForward };
|
||||||
const listLength = studentList.value.length;
|
|
||||||
let newOrder = 0;
|
|
||||||
|
|
||||||
if (type === "up") {
|
|
||||||
// 上一首:order减1,如果小于0则设置为列表最后一个元素的order
|
|
||||||
newOrder = order - 1 < 0 ? listLength - 1 : order - 1;
|
|
||||||
} else if (type === "down") {
|
|
||||||
// 下一首:order加1,如果大于等于列表长度则设置为0
|
|
||||||
newOrder = order + 1 >= listLength ? 0 : order + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cutStudent(newOrder);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { cutSong, getPlayUrl, handleBarDragBottomClick, startBarDragBottom, volumeShow, handleVolumeHide, handleVolumeShow, zeroOrderStudents, rePlay, playData, awardAudioList, changeInterval, awardMVList, bannerList, albumBoxRef, volume, handleVolumeClick, handleVolumeDrag, startDrag, stopDrag, toggleMute, isMuted, volume, cutStudent, studentList, studentIndex, scrollToPrevious, scrollToNext, changePointer, pointerIndex, visibleRef, studentRef, customRef, formatTime, currentTimeFormatted, durationFormatted, worksRef, introduceRef, customList, closeAll, manageAudio, progress, closePreview, openPreview, previewState, audioPlayer, trait, fastForward };
|
|
||||||
},
|
},
|
||||||
}).mount("#appIndex");
|
}).mount("#appIndex");
|
||||||
|
|||||||
Reference in New Issue
Block a user