惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
T
Tailwind CSS Blog
博客园_首页
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
J
Java Code Geeks
量子位
D
DataBreaches.Net
MongoDB | Blog
MongoDB | Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
C
Check Point Blog
V
Visual Studio Blog
H
Help Net Security
Recent Announcements
Recent Announcements
Engineering at Meta
Engineering at Meta

Hyde Blog

Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog Hyde Blog
Hyde Blog
Hyde · 2025-10-05 · via Hyde Blog

vue

<script setup lang="ts">
// import '../../lib/iconfont/iconfont';    // vitepress 基于 nodejs 的项目,无法引入需要window对象的模块

import { onMounted, ref } from "vue";
import { ElMessage } from "element-plus";
import PauseMusicController from "./PauseMusicController.vue";
import PlayingMusicController from "./PlayingMusicController.vue";
/**
 *
 * 音乐播放器
 */
const musics = [
  "周杰伦-搁浅.mp3",
  "林俊杰-不潮不用花钱.mp3",
  "林俊杰-可惜没如果.mp3",
  "林俊杰-美人鱼.mp3",
  "林俊杰-修炼爱情.mp3",
  "周杰伦-安静.mp3",
  "周杰伦-不能说的秘密.mp3",
  "周杰伦-彩虹.mp3",
  "周杰伦-断了的弦.mp3",
  "周杰伦-搁浅.mp3",
  "周杰伦-轨迹.mp3",
  "周杰伦-回到过去.mp3",
  "周杰伦-借口.mp3",
  "周杰伦-晴天.mp3",
  "周杰伦-退后.mp3",
];
// 当前音乐
const currentMusic = ref("/music/周杰伦-搁浅.mp3");
// 播放器元素
const audio = ref<HTMLAudioElement | null>();
// 是否播放音乐: 默认: false
const isPlayed = ref(false);
// 播放音乐的随机数字
let random = ref(0);
// 开一个定时器,什么时候需要销毁播放器可以直接清除该查询定时器
let music_palyer_timer = ref<ReturnType<typeof setInterval> | null>();
const playMusic = () => {
  /**
   * 浏览器为什么不能直接播放音乐参考博客:
   * https://blog.csdn.net/s18813688772/article/details/121103802
   */
  isPlayed.value = !isPlayed.value;
  const musicName =
    currentMusic.value
      .split("/")
      .pop()
      ?.replace(/\.mp3$/, "") ?? "未知歌曲";
  ElMessage({
    message: isPlayed.value ? `正在播放: ${musicName}` : `已暂停: ${musicName}`,
    type: isPlayed.value ? "success" : "warning",
    duration: 2000,
  });
  console.log("播放状态: ", isPlayed.value ? "播放" : "不播放");

  if (isPlayed.value) {
    // 如果是播放状态,则播放音乐
    audio.value?.play();
  } else {
    // 如果是暂停状态,则暂停音乐
    audio.value?.pause();

    const handleLoadError = () => {
      ElMessage.error("音乐加载失败,请重试");
    };
  }
};
const generateRandom = () => {
  /**
   * 生成一个与上次的数字不一样的数字
   */
  let tmp: number = Math.floor(Math.random() * musics.length);
  while (tmp === random.value) {
    tmp = Math.floor(Math.random() * musics.length);
  }
  return tmp;
};
onMounted(() => {
  // 挂在完成后给一个随机音乐
  random.value = generateRandom();
  console.log(
    `%c第${random.value + 1}首音乐.`,
    "color: green; font-weight: bolder;"
  );
  currentMusic.value = `/music/${musics[random.value]}`;

  // 提示用户可以播放音乐
  /* setTimeout(() => {
        confirm('点击右侧🎵可以播放音乐哦~');
    }, 100); */

  // 组件挂在完成即开启定时器监听音乐是否播放完成的状态
  music_palyer_timer.value = setInterval(function () {
    // 如果音频播放器获取到了,就监听是否结束的事件
    if (audio.value?.ended) {
      console.log("%c音乐结束, 下一曲~", "color: oranger; font-weight: bold;");
      // 以播放结束的标志判断
      random.value = generateRandom();
      console.log(
        `%c第${random.value}首音乐.`,
        "color: green; font-weight: bolder;"
      );
      currentMusic.value = `/music/${musics[random.value]}`;
      /*audio.value.onended = function () {
                // 以播放结束的事件监听形式控制
                let random: number = Math.floor(Math.random() * musics.length);
                currentMusic.value = `/music/${musics[random]}`;
                console.log('音乐结束, 下一曲~');
            }*/
    }
  }, 1000);
});

/**
 * 播放定时器的清除看情况 ...
 * Todo...
 */
</script>

<template>
  <div class="playMusic-wrapper">
    <button class="playMusic" @click="playMusic">
      <PlayingMusicController v-if="isPlayed" />
      <PauseMusicController v-else />
      <!-- <svg class="icon" aria-hidden="true">
                <use :xlink:href="`#icon-${isPlayed ? 'music' : 'play2'}`"></use>
            </svg> -->
    </button>
    <audio
      ref="audio"
      preload="auto"
      :autoplay="isPlayed"
      :src="currentMusic"
      style="display: none"
      controls
    ></audio>
  </div>
</template>

<style scoped lang="scss">
$PlayControler-width: 20px;
$PlayControler-height: 20px;

.playMusic-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 36px;
  // width: 400px; // 测试
  height: 36px;
  margin: 0 5px;

  .playMusic {
    width: $PlayControler-width;
    height: $PlayControler-width;
    border-radius: 20%;
    font-size: 1.3rem;
    line-height: 1.3rem;

    svg {
      margin: 0;
      padding: 0;
      width: $PlayControler-width;
      height: $PlayControler-width;
    }
  }
}
</style>