Vue3实现简易音乐播放器组件

前言

用Vue3实现一个简易的音乐播放器组件

其效果图如下所示:

实现这个组件需要提前做的准备:

  • 引入ElementUI
  • 引入字节跳动图标库
  • 一张唱见图片
  • 将要播放的音乐上传到文件服务器上,并提供一个能在线访问的链接【这里使用的是阿里云的OSS服务】

准备

ElementUI

ElementUI的引入可以参照其官网的引入方式;

字节跳动图标库

组件的【上一首】【播放】【下一首】【音量】等图标都是来源自这个图标库,这是其安装文档

在main.js中,我是这样引入的:

//引入字节跳动图标库
import {install} from '@icon-park/vue-next/es/all';
import '@icon-park/vue-next/styles/index.css';

......

//这种加载方式进行加载的话,代表使用默认的前缀进行加载:icon
//也就是说假如要使用一个主页图标,使用图标时标签该这么写: 
//<icon-home theme="outline" size="24" fill="#FFFFFF" :strokeWidth="2"/>
//install(app,'prefix') 用这种方式进行加载的话,可以自定义使用图标库时的标签前缀
install(app)

唱见图片

音乐源

将要播放的音乐放到文件服务器上,我这里是使用阿里云的OSS服务进行音乐文件的存储,然后在整个页面加载时【也就是在onMounted生命周期函数中获取这些数据源】。在后面的代码中,这一步体现在:

//初始化歌曲源
const initMusicArr = () => {
        requests.get("/Music/QueryAllMusic").then(function (res) {
            musicState.musicArr = res

            musicState.musicCount = res.length
        })
    }

    onMounted(() => {
        initMusicArr()

            ......
    })

完整代码

<template>

  <!--音乐播放器-->
  <div class="music-container" :class="{'music-active-switch': offsetThreshold}">
    <div class="music-disk">
      <!--唱片图片-->
      <img class="music-disk-picture" :class="{'music-disk-playing-style': playState}" src="./images/R-C.png"
           alt="">
    </div>

    <!--进度条-->
    <div class="music-slider">
      <el-slider
          v-model="playTime"
          :format-tooltip="tooltipFormat"
          size="small"
          :max="sliderLength"
          @change="changePlayTime"/>
    </div>

    <!--按钮组-->
    <div class="button-group">
      <!--上一曲 按钮-->
      <button class="play-button" @click="lastButtonClick">
        <icon-go-start theme="outline" size="23" fill="#939393" :strokeWidth="3" strokeLinejoin="miter"
                       strokeLinecap="butt"/>
      </button>
      <!--播放 按钮-->
      <button class="play-button" @click="playButtonClick">
        <icon-play-one v-if="!playState" theme="outline" size="23" fill="#939393" :strokeWidth="3"
                       strokeLinejoin="miter" strokeLinecap="butt"/>
        <icon-pause v-if="playState" theme="outline" size="23" fill="#939393" :strokeWidth="3"
                    strokeLinejoin="miter" strokeLinecap="butt"/>
      </button>
      <!--下一曲 按钮-->
      <button class="play-button" @click="nextButtonClick">
        <icon-go-end theme="outline" size="23" fill="#939393" :strokeWidth="3" strokeLinejoin="miter"
                     strokeLinecap="butt"/>
      </button>
      <!--音量按钮-->
      <div class="voice-container">
        <button class="voice-button" @click="voiceButtonClick">
          <icon-volume-notice v-if="!voiceMute" theme="outline" size="23" fill="#939393" :strokeWidth="3"
                              strokeLinejoin="miter" strokeLinecap="butt"/>
          <icon-volume-mute v-if="voiceMute" theme="outline" size="23" fill="#939393" :strokeWidth="3"
                            strokeLinejoin="miter" strokeLinecap="butt"/>
        </button>
        <div class="voice-slider">
          <el-slider
              v-model="voicePower"
              :max="1"
              :step="0.1"
              size="small"
              @change="changeVoicePower"/>
        </div>
      </div>
    </div>

    <audio
        ref="musicAudio"
        class="audio-component"
        controls
        preload="auto"
        @canplay="changeDuration">
      <source ref="musicSource" type="audio/mpeg"/>
    </audio>
  </div>

</template>

<script>
import {computed, onMounted, onUnmounted, reactive, ref, watch} from "vue";

//这里是自己封装的axios请求,可以将这里替换成自己的请求逻辑
import requests from "@/api/ajax";

export default {
  name: "index",
  setup() {

    //是否正在播放
    const playState = ref(false);

    //现在的播放时间
    const playTime = ref(0.00);

    //歌曲的时间长度
    const playDuration = ref(0.00);

    //进度条长度
    const sliderLength = ref(100);

    //歌曲URL
    const musicUrl = ref("");

    //播放器标签
    const musicAudio = ref(null);

    //实现音乐播放的标签
    const musicSource = ref(null);

    //是否静音
    const voiceMute = ref(false);

    //音量大小
    const voicePower = ref(0.5);

    const musicState = reactive({
      musicArr: [],
      musicCount: 0
    })

    const musicCursor = ref(0);

    //页面偏移量
    const pageOffset = ref(0)

    //是否达到阈值,达到阈值就显示播放器,反之
    const offsetThreshold = ref(false)

    //激活播放器
    const operateMusicPlayer = () => {
      pageOffset.value = window.scrollY
      //当页面滚动偏移达到800,激活用户框
      if (pageOffset.value > 800) {
        offsetThreshold.value = true
      } else {
        //反之
        offsetThreshold.value = false
      }
    }

    //播放按钮点击回调
    const playButtonClick = () => {

      if (playState.value) {
        musicAudio.value.pause()
      } else {
        musicAudio.value.play()
      }

      //修改播放时间【设置这个,当一首歌正常播放结束之后,再次点击播放按钮,进度条会得到重置】
      playTime.value = musicAudio.value.currentTime

      //重新设置播放状态
      playState.value = !playState.value
    }

    //上一曲按钮点击回调
    const lastButtonClick = () => {
      musicCursor.value -= 1

      changeMusic()
    }

    //下一曲按钮点击回调
    const nextButtonClick = () => {
      musicCursor.value += 1

      changeMusic()
    }

    //歌曲进度条文本提示
    const tooltipFormat = (val) => {

      let strTime = playTime.value

      let strMinute = parseInt(strTime / 60 + '')

      let strSecond = parseInt(strTime % 60 + '')

      return strMinute + ":" + strSecond
    }

    //当歌曲能播放时【亦即在canplay钩子函数中】,musicAudio.value.duration才不会是NaN,才能进行歌曲长度的设置
    const changeDuration = () => {
      if (playDuration.value != musicAudio.value.duration) {

        //修改进度条的最大值
        sliderLength.value = musicAudio.value.duration

        //修改歌曲播放时间
        playDuration.value = musicAudio.value.duration
      }
    }

    //el-slider的钩子函数,拖动进度条时快进歌曲,改变当前播放进度
    const changePlayTime = (val) => {
      musicAudio.value.currentTime = val
    }

    //音量按钮点击回调
    const voiceButtonClick = () => {
      voiceMute.value = !voiceMute.value

      if (!voiceMute.value) {
        voicePower.value = 1

        musicAudio.value.volume = 1
      } else {
        voicePower.value = 0

        musicAudio.value.volume = 0
      }
    }

    //el-slider的钩子函数,用于调节音量
    const changeVoicePower = (val) => {
      musicAudio.value.volume = val

      voicePower.value = val

      if (val > 0) {
        voiceMute.value = false
      } else {
        voiceMute.value = true
      }

    }

    //播放状态下,进度条里的数值每秒递增。而Audio因为在播放状态下,currentTime会自己递增,所以不用处理
    const updatePlayTimePerSecond = () => {
      if (playState.value) {
        playTime.value += 1

        if (playTime.value >= playDuration.value) {
          //代表当前歌曲已经播放完毕,进行切歌
          musicCursor.value++

          changeMusic()
        }
      }
    }

    //切歌
    const changeMusic = () => {
      //切歌【这里的music_url是后端返回给前端的json字符串中,用于存储歌曲在线链接的属性名是:music_url,所以要实现自己的请求逻辑,将这里的music_url改为自己的即可】
      musicSource.value.src = musicState.musicArr[musicCursor.value % musicState.musicCount].music_url

      // 当刷新了url之后,需要执行load方法才能播放这个音乐
      musicAudio.value.load()

      playTime.value = musicAudio.value.currentTime

      sliderLength.value = musicAudio.value.duration

      musicAudio.value.play()

      playState.value = true
    }

    //初始化歌曲源【将这里替换成自己的请求逻辑】
    const initMusicArr = () => {
      requests.get("/Music/QueryAllMusic").then(function (res) {
        musicState.musicArr = res

        musicState.musicCount = res.length

      })
    }

    onMounted(() => {
      initMusicArr()

      //播放状态下,使播放进度自增1,以与Audio内置的currentTime相匹配
      setInterval(updatePlayTimePerSecond, 1000)

      //添加滚动事件
      window.addEventListener("scroll", operateMusicPlayer)
    })

    onUnmounted(() => {
      window.removeEventListener("scroll", operateMusicPlayer)
    })

    return {
      musicAudio,
      musicSource,
      playState,
      playTime,
      playDuration,
      sliderLength,
      musicUrl,
      voiceMute,
      voicePower,
      musicState,
      musicCursor,
      pageOffset,
      offsetThreshold,
      playButtonClick,
      lastButtonClick,
      nextButtonClick,
      voiceButtonClick,
      tooltipFormat,
      changeMusic,
      changeDuration,
      changePlayTime,
      changeVoicePower,
      updatePlayTimePerSecond,
      initMusicArr
    }
  },
}
</script>

<style scoped>

.music-container {
  position: fixed;
  justify-content: center;
  width: 280px;
  height: 110px;
  background-color: white;
  border-radius: 15px;
  bottom: 15px;
  left: 10px;
  opacity: 0;
  transition: 0.5s;
}

.music-disk {
  position: absolute;
  width: 90px;
  height: 90px;
  left: 15px;
  top: 10px;
  border-radius: 50%;
}

.music-disk-picture {
  width: 90px;
  height: 90px;
  border-radius: 50%;
  /*设置图片不可点击*/
  pointer-events: none;
}

.music-disk-playing-style {
  animation: music-disk-rotate 5s linear infinite;
}

@keyframes music-disk-rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.button-group {
  position: absolute;
  width: 330px;
  height: 38px;
  left: 90px;
  bottom: 13px;
  margin-left: 10px;
}

.button-group > button {
  margin-left: 10px;
}

.play-button {
  float: left;
  width: 31px;
  height: 31px;
  padding: 4px;
  /*margin: 0px;*/
  border: 0px;
  border-radius: 50%;
  margin: 7px 0px 0px 0px;
}

.voice-button {
  float: left;
  width: 31px;
  height: 31px;
  padding: 0px;
  /*margin: 0px;*/
  border: 0px;
  border-radius: 50%;
  margin: 7px 0px 0px 0px;
  background-color: transparent;
}

.music-slider {
  position: absolute;
  top: 20px;
  left: 120px;
  width: 50%;
}

.voice-container {
  float: left;
  margin-left: 12px;
  width: 31px;
  height: 38px;
  overflow: hidden !important;
  transition: 0.5s;
}

.voice-container:hover {
  width: 160px;
}

.voice-slider {
  position: relative;
  top: 2px;
  right: -30px;
  width: 90px;
  height: 35px;
  background-color: white;
  border-radius: 10px;
  padding: 0px 15px 0px 15px;
  transition: 0.2s;
}

.audio-component {
  width: 300px;
  height: 200px;
  top: 100px;
  display: none;
}

.music-active-switch{
  opacity: 1;
}

</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于vue-video-player自定义播放器的方法

    先看一下效果. 图1--显示侧边栏 图2-收起侧边栏: 图三:全屏. 写在前面 本次项目中需要用到vue,vue-video-player,我用的是iview的ui框架,但是ui框架无妨,这里关注的是基于video.js开发的vue-video-player的使用,以及如何操作video.js中的api. vue-video-player 项目地址:https://github.com/surmon-china/vue-video-player. video.js文档地址:http://docs

  • vue音乐播放器插件vue-aplayer的配置及其使用实例详解

    昨天在vue的官网上看到vue-aplayer这个音乐播放器的插件,由于个人有比较喜欢音乐,所以就拿过来玩一玩,感觉还是比较实用的,界面美观. 首先,我们先安装 npm install vue-aplayer --save ,之后在组件中引入  import VueAplayer from 'vue-aplayer',下面就是源码,可供参考: <template> <div> <div style="padding:10px 0;"> <a-p

  • 基于vue-element组件实现音乐播放器功能

    最近在写一个基于 github-page 和 gist 的博客, 想加个音乐播放器, 做了一个早上, 发出来分享一下 演示地址 https://github-laziji.github.io 效果 使用到的组件 element组件 布局 Layout 按钮 Button 滑块 Slider 进度条 Progress 弹出框 Popover html5组件 audio 实现代码 更详细的实现可以看 https://github.com/GitHub-Laziji/vblog <template>

  • vue + element ui实现播放器功能的实例代码

    没有效果图的展示都是空口无凭 1.基于audio并结合elementUI 的进度条实现 2.实现了播放器基本的功能,播放/暂停.快进.静音.调节声音大小.下载等功能 html代码,关键部分已加注释 <div class="right di main-wrap" v-loading="audio.waiting"> <!-- 此处的ref属性,可以很方便的在vue组件中通过 this.$refs.audio获取该dom元素 --> <au

  • vue一个页面实现音乐播放器的示例

    本文介绍了vue一个页面实现音乐播放器的示例,分享给大家,具体如下: 效果如下: 项目地址:https://github.com/ermu592275254/MiniMusicPlayer 演示地址: https://ermu592275254.github.io/MiniMusicPlayer/(歌曲链接已失效) 开发前构思 界面 做音乐播放器,界面一定要炫酷.太low了听歌没感觉.本身是为了在上班的时候用,于是做成了一个类似网易云音乐的界面,大小合适.不用兼容手机端. 用css做图标 本怀着

  • vue-dplayer 视频播放器实例代码

    官网 vue-dplayer dplayer-doc 示例 如果默认 options 中没有视频链接,之后设置视频链接时,直接通过 this.options.video.url = videoPath 是无效的 需要先获取到播放器的实例 this.$refs.player.dp ,然后通过 switchVideo() 对 url 进行修改 <template> <d-player ref="player" :options="options">

  • 适用于 Vue 的播放器组件Vue-Video-Player操作

    如果h5的标签<vedio>不能满足你的需求,那就用这个组件Vue-Video-Player吧,也许可以覆盖到你的需求. <video-player class="video-player vjs-custom-skin" ref="videoPlayer" :playsinline="true" :options="playerOptions" ></video-player> 配置参数:

  • vue-video-player视频播放器使用配置详解

    本文实例为大家分享了vue-video-player视频播放器的使用配置,供大家参考,具体内容如下 1.安装 npm install vue-video-player -save 2.在main.js中添加 import VueVideoPlayer from 'vue-video-player' // 视频播放器 import 'video.js/dist/video-js.css' Vue.use(VueVideoPlayer) 3.新建一个vueVideoPlayer.vue组件供调用 <

  • vue实现自定义H5视频播放器的方法步骤

    前言 前段时间基于vue写了一个自定义的video播放器组件,踩了一些小坑, 这里做一下复盘分享出来,避免日后重复踩坑... 设计阶段 这里就直接放几张完成后的播放状态图吧,界面布局基本就是flex+vw适配一把梭,也比较容易. 需要实现的几个功能基本都标注出来了; 除了还有一个视频加载失败的...下面就这届上代码了;刚开始构思的时候考虑了一下功能的实现方式: 一是用原生的DOM操作,获取video元素后,用addEventListener来监听; 二是用vue的方式绑定事件监听; 最后图方便采

  • vue-music关于Player播放器组件详解

    本文实例为大家分享了关于Player播放器组件的具体内容,供大家参考,具体内容如下 迷你播放器: 1.播放器组件会在各个页面的情况下会打开. 首先在vuex state.js 中定义全局的播放器状态 import {playMode} from 'common/js/config.js'; const state = { singer:{}, playing:false, //是否播放 fullScreen:false, //是否全屏 playList:[], //播放列表 sequenceLi

随机推荐