论述题亿唐网不做网站做品牌,设计店名logo,谁家网站做的好,装修网站建设若没有打开播放音乐标签页#xff0c;则打开新标签页播放所选音乐如果已打开新标签页#xff0c;则直接切换所选音乐 pageA.vue
script setup langts
const tab2 refany(null);
const router useRouter();interface Track {id: number;name: …若没有打开播放音乐标签页则打开新标签页播放所选音乐如果已打开新标签页则直接切换所选音乐 pageA.vue
script setup langts
const tab2 refany(null);
const router useRouter();interface Track {id: number;name: string;url: string;
}
const tracks reactiveTrack[]([{id: 1,name: Sample Track 1,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3,},{id: 2,name: Sample Track 2,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3,},{id: 3,name: Sample Track 3,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3,},{id: 4,name: Sample Track 4,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-4.mp3,},{id: 5,name: Sample Track 5,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3,},{id: 6,name: Sample Track 6,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-6.mp3,},{id: 7,name: Sample Track 7,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-7.mp3,},{id: 8,name: Sample Track 8,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-8.mp3,},{id: 9,name: Sample Track 9,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-9.mp3,},{id: 10,name: Sample Track 10,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-10.mp3,},
]);
const openWindow (track: Track) {// 如果标签页 2 已经存在且未关闭if (tab2.value !tab2.value.closed) {// 激活标签页 2tab2.value.focus();const channel new BroadcastChannel(myChannel);channel.postMessage(JSON.stringify(track));channel.close();} else {const target router.resolve({path: communicationB,query: { isNew: 1, track: JSON.stringify(track) },});// 如果标签页 2 不存在或已经关闭则打开新的标签页tab2.value window.open(target.href, _blank);}
};
/scripttemplatediv classmusic-listh1Music Playlist/h1ulliv-fortrack in tracks:keytrack.idclasstrack-itemclickopenWindow(track)span{{ track.name }}/span/li/ul/div
/templatestyle scoped langscss
.music-list {max-width: 500px;padding: 20px;margin: 0 auto;background: linear-gradient(145deg, #f0f4ff, #cfd9ff);border-radius: 20px;box-shadow:5px 5px 15px rgb(0 0 0 / 10%),-5px -5px 15px rgb(255 255 255 / 70%);
}h1 {margin-bottom: 20px;font-size: 24px;font-weight: bold;color: #333;text-align: center;letter-spacing: 1px;
}ul {padding: 0;list-style-type: none;
}.track-item {display: flex;align-items: center;justify-content: space-between;padding: 15px;margin-bottom: 15px;cursor: pointer;background: #fff;border-radius: 12px;box-shadow:3px 3px 8px rgb(0 0 0 / 10%),-3px -3px 8px rgb(255 255 255 / 70%);transition:transform 0.2s,box-shadow 0.2s;
}.track-item:hover {box-shadow:8px 8px 20px rgb(0 0 0 / 15%),-8px -8px 20px rgb(255 255 255 / 70%);transform: translateY(-5px);
}span {font-size: 18px;font-weight: 500;color: #333;letter-spacing: 0.5px;
}
/stylepageB.vue
templatediv classmusic-listh1Music Playlist/h1ulli v-fortrack in tracks :keytrack.id classtrack-itembutton:class{ active: currentTrack?.id track.id }clickplayMusic(track){{ track.name }}/button/li/ul!-- 进度条 --div v-ifcurrentTrack?.url classprogress-container relativespanv-ifcurrentTrack.nameclassabsolute left-50% transform-translate-x--50% bottom-20px{{ currentTrack?.name }}/spanspan{{ formatTime(currentTime) }}/spanprogress :valuecurrentTime :maxduration /span{{ formatTime(duration) }}/spanbutton class!w-64px ml-10px clicktogglePlay{{ isPlaying ? Pause : Play }}/button/divaudio refaudioPlayer timeupdateupdateProgress endedonTrackEnd //div
/templatescript langts
import { ref, reactive, onMounted } from vue;
const channel refany();interface Track {id: number;name: string;url: string;
}export default {setup() {const tracks reactiveTrack[]([{id: 1,name: Sample Track 1,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3,},{id: 2,name: Sample Track 2,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3,},{id: 3,name: Sample Track 3,url: https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3,},]);const currentTrack refTrack();const audioPlayer refHTMLAudioElement | null(null);const currentTime ref(0); // 当前播放时间const duration ref(0); // 当前音频时长const isPlaying ref(false); // 播放状态const playMusic (track: Track) {if (audioPlayer.value) {currentTrack.value track;audioPlayer.value.src track.url;audioPlayer.value.play();isPlaying.value true;// 每次播放新音乐时重置进度currentTime.value 0;console.log(currentTime);duration.value 0;}};const updateProgress () {if (audioPlayer.value) {currentTime.value audioPlayer.value.currentTime; // 当前时间duration.value audioPlayer.value.duration || 0; // 总时长}};const onTrackEnd () {isPlaying.value false; // 播放结束时暂停状态const index tracks.findIndex((t) t.id currentTrack.value!.id);if (currentTrack.value!.url index tracks.length - 1) {const track tracks[index 1];playMusic(track); // 自动播放下一首} else {currentTrack.value {id: -1,name: ,url: ,}; // 播放结束}};// 播放或暂停const togglePlay () {if (audioPlayer.value) {if (isPlaying.value) {audioPlayer.value.pause();} else {audioPlayer.value.play();}isPlaying.value !isPlaying.value;}};const onPlay () {isPlaying.value true;if (audioPlayer.value) {audioPlayer.value.play();}};const formatTime (time: number): string {const minutes Math.floor(time / 60);const seconds Math.floor(time % 60).toString().padStart(2, 0);return ${minutes}:${seconds};};onMounted(() {if (audioPlayer.value) {audioPlayer.value.volume 0.8; // 设置默认音量}channel.value new BroadcastChannel(myChannel);channel.value.onmessage (event: any) {const data JSON.parse(event.data);if (data.id ! currentTrack.value?.id) {playMusic(data);}onPlay();};});onMounted(() {const route useRoute();const router useRouter();const { query } route as any;// 判断是否是新打开的标签页if (query.isNew 1) {console.log(query);// 清空地址栏参数router.replace({ query: {} });playMusic(JSON.parse(query.track));}});onBeforeUnmount(() {channel.value.close();});return {tracks,currentTrack,currentTime,duration,playMusic,updateProgress,onTrackEnd,formatTime,audioPlayer,togglePlay,isPlaying,};},
};
/scriptstyle scoped
.music-list {max-width: 600px;padding: 20px;margin: 0 auto;background-color: #f4f4f4;border-radius: 8px;box-shadow: 0 2px 10px rgb(0 0 0 / 10%);
}h1 {color: #333;text-align: center;
}ul {padding: 0;list-style-type: none;
}.track-item {margin: 10px 0;
}button {width: 100%;padding: 10px;font-size: 16px;color: white;cursor: pointer;background-color: #6200ea;border: none;border-radius: 4px;transition: background-color 0.3s;
}button.active {background-color: #3700b3;
}button:hover {background-color: #5c00d2;
}.progress-container {display: flex;align-items: center;justify-content: space-between;margin-top: 20px;
}progress {flex: 1;height: 6px;margin: 0 10px;appearance: none;background-color: #ddd;
}progress::-webkit-progress-bar {background-color: #ddd;
}progress::-webkit-progress-value {background-color: #6200ea;
}progress::-moz-progress-bar {background-color: #6200ea;
}span {font-size: 14px;color: #333;
}
/style