Skip to content

音乐播放器

简介

给你的 vitepress 添加音乐播放器,让你的网站更加有活力。

版权

版权声明

本文是在 博主程序员皮蛋鸽鸽 💻 网站:极客兔 - 笔记站》 看到的 nav 导航栏音乐播放器。在基础上增加了自己实践过程的一些细节,转载无需和我联系,但请注明文章来源。如果侵权之处,请联系博主进行删除,谢谢~

安装依赖

注意

基于作者的 vue 组件用了 element-plus 组件提示,所以需要安装 element-plus 组件,不需要可以跳过。

sh
pnpm install element-plus
sh
npm install element-plus --save
sh
yarn add element-plus

新建组件

  • docs\.vitepress\theme\components\配置以下代码
点我查看
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>
vue
// 暂停时图标
<template>
  <svg
    t="1744867867712"
    class="icon"
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="7482"
    width="256"
    height="256"
  >
    <path
      d="M934.4 53.333333c-29.866667-23.466667-68.266667-32-104.533333-23.466666L334.933333 145.066667c-55.466667 12.8-96 61.866667-96 119.466666v443.733334c-14.933333-6.4-32-8.533333-49.066666-8.533334-81.066667 0-147.2 66.133333-147.2 147.2s66.133333 147.2 147.2 147.2c81.066667 0 147.2-66.133333 147.2-147.2V492.8l544-125.866667v341.333334c-14.933333-6.4-32-8.533333-49.066667-8.533334-81.066667 0-147.2 66.133333-147.2 147.2 0 81.066667 66.133333 147.2 147.2 147.2 78.933333 0 142.933333-59.733333 147.2-136.533333 0-4.266667 2.133333-6.4 2.133333-10.666667V151.466667c0-38.4-17.066667-74.666667-46.933333-98.133334zM339.2 390.4v-125.866667c0-10.666667 8.533333-21.333333 19.2-23.466666L851.2 128c10.666667-2.133333 17.066667 2.133333 21.333333 4.266667 4.266667 2.133333 8.533333 8.533333 8.533334 19.2v115.2l-541.866667 123.733333z"
      fill="#80B8F8"
      p-id="7483"
      data-spm-anchor-id="a313x.search_index.0.i37.3afb3a81G2wgGd"
      class="selected"
    ></path>
  </svg>
</template>
vue
// 播放时图标
<template>
  <svg
    t="1706712309791"
    class="icon"
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="1184"
    width="200"
    height="200"
  >
    <path
      d="M983.38 306.44l-442.628 81.458a17.454 17.454 0 0 0-14.302 17.162v375.822c-31.38-18.59-72.608-24.724-113.914-13.666-74.146 19.85-120.418 87.528-103.352 151.164s91.006 99.13 165.152 79.28c65.884-17.638 109.718-73.042 106.704-129.814h0.188V469.482l367.992-67.74v289.742c-31.38-18.59-72.61-24.724-113.914-13.666-74.146 19.85-120.418 87.528-103.352 151.164 17.066 63.636 91.006 99.13 165.152 79.28 64.794-17.348 108.296-71.218 106.852-126.998H1004l0.008-457.66c0.002-10.906-9.896-19.14-20.628-17.164z"
      fill="#707AFA"
      p-id="1185"
    ></path>
    <path
      d="M474.336 977.676c-74.146 19.85-148.086-15.644-165.152-79.28a103.588 103.588 0 0 1-3.038-16.91c-1.166 12.202-0.254 24.62 3.038 36.894 17.066 63.636 91.006 99.13 165.152 79.28 65.884-17.638 109.718-73.042 106.704-129.814h0.188v-19.984h-0.188c3.014 56.774-40.82 112.176-106.704 129.814zM1004 761.28h-0.042c1.444 55.78-42.058 109.652-106.852 126.998-74.146 19.85-148.086-15.644-165.152-79.28a103.588 103.588 0 0 1-3.038-16.91c-1.166 12.202-0.254 24.62 3.038 36.894 17.066 63.636 91.006 99.13 165.152 79.28 64.794-17.348 108.296-71.218 106.852-126.998H1004l0.008-457.66v-0.006L1004 761.28z"
      fill="#6770E6"
      p-id="1186"
    ></path>
    <path
      d="M487.55 167.318c-30.86-99.616-129.14-131.888-191.96-142.34-15.806-2.62-31.02-3.864-41.386-4.454a12.668 12.668 0 0 0-13.394 12.65v378.478c-31.38-18.59-72.61-24.726-113.916-13.668-74.146 19.85-120.418 87.528-103.352 151.164 17.066 63.636 91.006 99.13 165.152 79.28 65.884-17.638 109.716-73.042 106.704-129.814h0.192V150.392c35.96 2.658 84.72 19.644 130.94 79.312 67.62 87.246 154.7 51.036 154.7 51.036-39.7 0.002-75.24-53.872-93.68-113.422z"
      fill="#FF8354"
      p-id="1187"
    ></path>
    <path
      d="M188.692 607.944c-74.146 19.85-148.086-15.644-165.152-79.28a103.55 103.55 0 0 1-3.008-16.66c-1.204 12.282-0.306 24.79 3.008 37.146 17.066 63.636 91.006 99.13 165.152 79.28 65.884-17.638 109.716-73.042 106.704-129.814h0.192v-20.486h-0.192c3.014 56.774-40.82 112.176-106.704 129.814z"
      fill="#E0734A"
      p-id="1188"
    ></path>
    <path
      d="M126.894 437.954c41.306-11.058 82.536-4.924 113.916 13.668v-39.966c-31.38-18.59-72.61-24.726-113.916-13.668-71.43 19.122-116.964 82.634-104.95 144.156 9.03-47.094 49.064-89.228 104.95-104.19z"
      fill="#FFAC8C"
      p-id="1189"
    ></path>
    <path
      d="M540.752 427.864l442.628-81.456c10.728-1.974 20.62 6.252 20.628 17.148v-39.952c0-10.904-9.896-19.138-20.628-17.162l-442.628 81.456a17.456 17.456 0 0 0-14.302 17.162v39.966a17.454 17.454 0 0 1 14.302-17.162zM835.308 717.784c41.306-11.058 82.534-4.924 113.914 13.666v-39.966c-31.38-18.59-72.61-24.724-113.914-13.666-71.43 19.124-116.964 82.634-104.95 144.156 9.03-47.094 49.064-89.228 104.95-104.19zM412.536 807.182c41.304-11.058 82.532-4.924 113.914 13.666v-39.966c-31.38-18.59-72.608-24.724-113.914-13.666-71.43 19.124-116.964 82.634-104.948 144.156 9.03-47.092 49.064-89.228 104.948-104.19z"
      fill="#8F95E6"
      p-id="1190"
    ></path>
    <path
      d="M244.204 54.496c10.366 0.59 25.582 1.834 41.386 4.454 62.82 10.452 161.1 42.724 191.96 142.34 10.292 33.238 25.916 64.698 44.612 86.018 33.838 3.914 59.066-6.566 59.066-6.566-39.7 0-75.24-53.874-93.68-113.424-30.86-99.616-129.14-131.888-191.96-142.34-15.806-2.618-31.02-3.864-41.386-4.454a12.668 12.668 0 0 0-13.394 12.65v21.598a12.806 12.806 0 0 1 3.396-0.276z"
      fill="#FFAC8C"
      p-id="1191"
    ></path>
    <path
      d="M865.658 118.83c-9.74 0-17.636-7.89-17.636-17.62 0-9.378-7.082-17.566-16.448-18.172-10.264-0.664-18.796 7.456-18.796 17.568v0.604c0 9.732-7.896 17.62-17.636 17.62-9.386 0-17.58 7.076-18.186 16.434-0.664 10.254 7.462 18.78 17.582 18.78h0.604c9.74 0 17.636 7.89 17.636 17.62 0 9.378 7.082 17.566 16.448 18.172 10.264 0.664 18.796-7.456 18.796-17.568v-0.604c0-9.732 7.896-17.62 17.636-17.62h0.604c10.12 0 18.248-8.524 17.584-18.78-0.608-9.358-8.804-16.434-18.188-16.434zM188.01 811.662c-13.588 0-24.602-11.006-24.602-24.582 0-13.082-9.88-24.504-22.946-25.35-14.318-0.926-26.22 10.402-26.22 24.508v0.842c0 13.576-11.014 24.582-24.602 24.582-13.092 0-24.524 9.872-25.37 22.926-0.928 14.306 10.41 26.198 24.528 26.198h0.844c13.588 0 24.602 11.006 24.602 24.582 0 13.082 9.88 24.504 22.946 25.35 14.318 0.926 26.22-10.402 26.22-24.508v-0.842c0-13.576 11.014-24.582 24.602-24.582h0.844c14.118 0 25.456-11.892 24.53-26.198-0.85-13.054-12.282-22.926-25.376-22.926z"
      fill="#69EBFC"
      p-id="1192"
    ></path>
  </svg>
</template>

注册组件

  • docs\.vitepress\theme\components\TeekLayoutProvider.vue 中注册组件
vue
<script setup lang="ts" name="TeekLayoutProvider">
import MusicPlayer from "./MusicPlayer.vue"; // 引入音乐播放器组件
</script>

<template>
  <Teek.Layout>
    <template #nav-bar-content-after>
      <div :class="ns.b('appearance')">...</div>
      <!-- 音乐播放器组件 -->
      <MusicPlayer />
    </template>
  </Teek.Layout>
</template>

配置音乐

  • docs\public\music 目录下放置音乐文件
md
docs
├── public
│ ├── music
│ │ ├── 周杰伦-搁浅.mp3
│ │ ├── 林俊杰-不潮不用花钱.mp3
│ │ └── 林俊杰-可惜没如果.mp3
最近更新