链接全是线上的直接在vs里运行即可用,使用es6语法书写的。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue Music Player with Image Spin Control</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
height: 90vh;
}
button{
/* 清除默认边框 */
border:0;
outline:none;
/*清除默认背景 */
background-color: transparent;
padding: 25px;
}
.music-player {
text-align: center;
position: relative;
bottom: 0;
}
audio {
width: 300px;
}
.disc-container {
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.disc {
width: 20vw;
height: 20vw;
border-radius: 50%;
background-size: cover;
animation: spin 20s linear infinite;
border: 20px solid rgba(30, 29, 29, 0.5); /* 添加边框 */
}
</style>
</head>
<body>
<div id="app">
<div class="music-player">
<audio ref="audioPlayer" controls @play="startImageSpin" @pause="stopImageSpin" @ended="stopImageSpin">
<source :src="currentSong.url" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<h2>{{ currentSong.title }}</h2>
<button @click="playPrevious">
<svg t="1730998212948" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1026" width="30" height="30"><path d="M256 224a32 32 0 0 1 32 32v512a32 32 0 0 1-64 0V256a32 32 0 0 1 32-32z m385.952 30.624a96 96 0 0 1 157.44 73.76v366.72a96 96 0 0 1-157.44 73.76l-220.032-183.36a96 96 0 0 1 0-147.52z m86.048 53.28a32 32 0 0 0-45.056-4.096l-220.032 183.36a32 32 0 0 0-4.096 4.096l-2.4 3.232a32 32 0 0 0 6.496 41.824l220.032 183.36a32 32 0 0 0 52.48-24.576v-366.72a32 32 0 0 0-7.424-20.48z" fill="#000000" p-id="1027"></path></svg>
</button>
<button @click="togglePlayPause">
<svg t="1730998261628" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1330" width="30" height="30"><path d="M608.352 442.176a64 64 0 0 1 33.92 9.728l163.648 102.272a64 64 0 0 1 0 108.544l-163.648 102.272a64 64 0 0 1-97.92-54.272v-204.544a64 64 0 0 1 64-64zM448 704a32 32 0 0 1 0 64H224a32 32 0 0 1 0-64h224z m160.352-197.824v204.544l163.648-102.272-163.648-102.272zM448 448a32 32 0 0 1 0 64H224a32 32 0 0 1 0-64h224z m352-256a32 32 0 0 1 0 64H224a32 32 0 1 1 0-64h576z" fill="#000000" p-id="1331"></path></svg>
</button>
<button @click="playNext">
<svg t="1730998244067" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1177" width="30" height="30"><path d="M768 224a32 32 0 0 1 32 32v512a32 32 0 0 1-64 0V256a32 32 0 0 1 32-32z m-386.336 31.36l220.032 183.36a96 96 0 0 1 0 147.52l-220.032 183.36a96 96 0 0 1-157.44-73.76v-366.72a96 96 0 0 1 157.44-73.76zM295.616 308.64a32 32 0 0 0-7.424 20.48v366.72a32 32 0 0 0 52.48 24.576l220.032-183.36a32 32 0 0 0 6.496-41.824l-2.4-3.264a32 32 0 0 0-4.096-4.096l-220.032-183.36a32 32 0 0 0-45.056 4.128z" fill="#000000" p-id="1178"></path></svg>
</button>
</div>
<div class="disc-container">
<div class="disc" :style="`background-image: url(${currentImage})`" ref="disc"></div>
</div>
</div>
<script>
const { createApp, ref, computed, onMounted } = Vue;
createApp({
setup() {
const audioPlayer = ref(null);
const discElement = ref(null);
const currentSongIndex = ref(0);
const songs = ref([
{ title: 'love my life', url: 'https://dlink.host/sharepoint/aHR0cHM6Ly9vbmVkcnYtbXkuc2hhcmVwb2ludC5jb20vOnU6L2cvcGVyc29uYWwvc3Rvcl9vbmVkcnZfb25taWNyb3NvZnRfY29tL0VabnZ0azhrRTI5TW5OdVR6WjRqWDB3Qm5jbnZTRHhYODAxM3RkbDBTZEszb1E.mp3', image: 'https://ts1.cn.mm.bing.net/th/id/R-C.287b85fd021e852cb71838589ee8c2ee?rik=45qFAASOHsQsUg&riu=http%3a%2f%2fwww.bing.yiyuen.com%2fapi%2fbing%2fwallpaper%2fgetSource%3fid%3d2492&ehk=haEuZL0kY%2fYBg22TnqK1rBVgNfl23ZpT%2f3YhQL6xUps%3d&risl=&pid=ImgRaw&r=0' },
{ title: '老街', url: 'https://dlink.host/musics/aHR0cHM6Ly9vbmVkcnYtbXkuc2hhcmVwb2ludC5jb20vOnU6L2cvcGVyc29uYWwvc3Rvcl9vbmVkcnZfb25taWNyb3NvZnRfY29tL0VkcjU3elIxemcxQ2pxOWFXY2FGMG1rQkszQUF5VXlqNTNxRWlfMl9BdWRwRHc.mp3', image: 'https://n.sinaimg.cn/sinakd20116/580/w690h690/20200418/f087-iskepxt3819684.jpg' },
{ title: '流沙', url: 'https://dlink.host/musics/aHR0cHM6Ly9vbmVkcnYtbXkuc2hhcmVwb2ludC5jb20vOnU6L2cvcGVyc29uYWwvc3Rvcl9vbmVkcnZfb25taWNyb3NvZnRfY29tL0VYSldHSzUwZmRGUHRHdVdUYVlVT21NQjlhM012UnR6OHFMakR4NWlHU2xsZGc.mp3', image: 'https://tse2-mm.cn.bing.net/th/id/OIP-C.Oy3BxwSSlARWVcca0IFCcAEsDv?rs=1&pid=ImgDetMain' }
]);
const currentImage = ref(songs.value[0].image);
const currentSong = computed(() => songs.value[currentSongIndex.value]);
function playPrevious() {
if (currentSongIndex.value > 0) {
currentSongIndex.value--;
} else {
currentSongIndex.value = songs.value.length - 1;
}
updateImage();
audioPlayer.value.load();
audioPlayer.value.play();
}
function playNext() {
if (currentSongIndex.value < songs.value.length - 1) {
currentSongIndex.value++;
} else {
currentSongIndex.value = 0;
}
updateImage();
audioPlayer.value.load();
audioPlayer.value.play();
}
function togglePlayPause() {
if (audioPlayer.value.paused) {
audioPlayer.value.play();
} else {
audioPlayer.value.pause();
}
}
function startImageSpin() {
discElement.value.style.animationPlayState = 'running';
}
function stopImageSpin() {
discElement.value.style.animationPlayState = 'paused';
}
function updateImage() {
// Reset the rotation to 0 degrees
discElement.value.style.transform = 'rotate(0deg)';
currentImage.value = currentSong.value.image;
}
onMounted(() => {
discElement.value = document.querySelector('.disc');
updateImage();
stopImageSpin();
});
return {
currentSong,
playPrevious,
playNext,
togglePlayPause,
startImageSpin,
stopImageSpin,
currentImage,
audioPlayer
};
}
}).mount('#app');
</script>
</body>
</html>