vue + element UI【实战】音乐播放器/语音条(内含音频的加载、控制,事件监听,信息获取,手机网页阴影的去除等技巧)

简介: vue + element UI【实战】音乐播放器/语音条(内含音频的加载、控制,事件监听,信息获取,手机网页阴影的去除等技巧)

相关技巧,详见注释

<template>
  <!-- 音乐播放器 -->
  <div class="container">
    <h2>{{ musicName }}</h2>
    <audio
      ref="Ref_audioPlayer"
      controls
      :src="audioPathDic[musicName]"
      @ended="overAudio"
      @pause="onPause"
      @play="onPlay"
      @loadeddata="loadeddata"
      @timeupdate="timeupdate"
    ></audio>
    <div>
      <el-tag>{{ msg }}</el-tag>
    </div>

    <div class="listBox">
      <h3 class="subTitle">原创面板</h3>

      <div class="myPlayer">
        <el-slider
          @mousedown="isDraging = 'true'"
          @mouseup="isDraging = 'false'"
          @change="currentRateChange"
          v-model="currentRate"
          :marks="marks"
          :show-tooltip="false"
        >
        </el-slider>
        <div class="controlBox">
          <i @click="move(-5)" class="el-icon-d-arrow-left"></i>
          <i
            type="primary"
            v-if="playstatus"
            @click="pause"
            class="el-icon-video-pause"
          ></i>
          <i type="primary" v-else @click="play" class="el-icon-video-play"></i>
          <i @click="replay" class="el-icon-refresh-left"></i>
          <i @click="move(5)" class="el-icon-d-arrow-right"></i>
        </div>
      </div>
      <h3 class="subTitle">播放列表</h3>
      <ul>
        <li
          @click="changeMusice(key)"
          class="musicItem"
          v-for="(value, key) in audioPathDic"
          :key="key"
        >
          {{ key }}
        </li>
      </ul>
      <h3 class="subTitle">获取信息</h3>
      <div class="btnBox">
        <el-button @click="getLength" type="primary" size="small"
          >获取时长</el-button
        >
        <el-button @click="getCurrentTime" type="primary" size="small"
          >获取播放进度</el-button
        >
        <el-button @click="getPlayStatus" type="primary" size="small"
          >获取播放状态</el-button
        >
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      playstatus: false,
      isDraging: false,
      marks: {
        0: "0",
        100: "100",
      },
      currentRate: 0,
      msg: "待播放",
      // 歌曲名称
      musicName: "祝福你",
      audioPathDic: {
        不再犹豫: require("@/pages/music/cantopop/audios/《不再犹豫》Beyond_粤语.mp3"),
        祝福你: require("@/pages/music/cantopop/audios/《祝福你》群星_粤语.mp3"),
      },
    };
  },
  methods: {
    // 监听audio标签的音频加载完成事件
    loadeddata() {
      // 需等音频加载完成,才能获取到音频的时长
      this.marks["100"] = this.s_to_MS(this.$refs.Ref_audioPlayer.duration);
    },

    // 监听audio标签的播放事件
    onPlay() {
      this.msg = "播放中";
      this.playstatus = true;
    },
    // 监听audio标签的暂停事件
    onPause() {
      this.msg = "已暂停";
      this.playstatus = false;
    },
    // 监听audio标签的停止播放事件
    overAudio() {
      this.msg = "播放结束";
      this.playstatus = false;
    },
    // 监听audio标签的播放进度改变事件
    timeupdate(e) {
      // 使用this.isDraging来控制,当拖拽进度条的过程中,停止对进度的更新——用于解决bug:拖动进度条自动回弹
      if (!this.isDraging) {
        this.currentRate = Math.floor(
          (e.target.currentTime / this.$refs.Ref_audioPlayer.duration) * 100
        );

        this.marks["0"] = this.s_to_MS(e.target.currentTime);
      }
    },

    // 秒数转换分+秒
    s_to_MS(s) {
      let m;
      m = Math.floor(s / 60);
      s = Math.floor(s % 60);
      m += "";
      s += "";
      s = s.length == 1 ? "0" + s : s;
      if (isNaN(m)) {
        return "&infin;";
      }
      return m + ":" + s;
    },

    // 切换音乐
    changeMusice(newMusicName) {
      this.musicName = newMusicName;
      this.$nextTick(() => {
        this.$refs.Ref_audioPlayer.play();
      });
    },

    // 原创面板——播放
    play() {
      this.$refs.Ref_audioPlayer.play();
    },

    // 原创面板——暂停
    pause() {
      this.$refs.Ref_audioPlayer.pause();
    },

    // 原创面板——重新播放
    replay() {
      this.$refs.Ref_audioPlayer.currentTime = 0;
      this.$refs.Ref_audioPlayer.play();
    },

    // 原创面板——前进、后退——改变当前播放位置
    move(val) {
      this.$refs.Ref_audioPlayer.currentTime += val;
      this.$refs.Ref_audioPlayer.play();
    },

    // 原创面板——点击/拖拽原创面板进度条
    currentRateChange(newVal) {
      this.$refs.Ref_audioPlayer.currentTime = Math.round(
        (newVal / 100) * this.$refs.Ref_audioPlayer.duration
      );
      this.$refs.Ref_audioPlayer.play();
    },

    // 获取播放状态
    getPlayStatus() {
      this.$notify.info({
        title: "当前播放状态",
        message: this.$refs.Ref_audioPlayer.paused ? "已暂停" : "播放中",
      });
    },

    // 获取播放进度
    getCurrentTime() {
      // 已播放时长(单位秒s)
      let totalSeconds = this.$refs.Ref_audioPlayer.currentTime;
      // 分钟数
      let minites = Math.floor(totalSeconds / 60);
      // 秒数
      let seconds = Math.floor(totalSeconds % 60);

      this.$notify.info({
        title: "当前进度",
        message: `${minites}分${seconds}秒`,
      });
    },

    // 获取音频时长
    getLength() {
      // 时长(单位秒s)
      let totalSeconds = this.$refs.Ref_audioPlayer.duration;
      // 分钟数
      let minites = Math.floor(totalSeconds / 60);
      // 秒数
      let seconds = Math.floor(totalSeconds % 60);

      this.$notify.info({
        title: "时长",
        message: `${minites}分${seconds}秒`,
      });
    },
  },
};
</script>

<style scoped>
.btnBox {
  display: flex;
  justify-content: space-evenly;
  flex-wrap: wrap;
  align-content: space-around;
}
.container {
  text-align: center;
  max-width: 500px;
  margin: auto;
}
.listBox {
  text-align: left;
}
.subTitle {
  margin-left: 40px;
}
.musicItem {
  line-height: 40px;
  cursor: pointer;
}

.myPlayer {
  border: 4px solid #409eff;
  border-radius: 10px;
  padding: 10px 20px;
  margin: 10px;
}
.controlBox {
  display: flex;
  justify-content: space-evenly;
  font-size: 30px;
  color: #409eff;
}

/* 去除手机网页点击事件的阴影 */
* {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-tap-highlight-color: transparent;
}
</style>

获取播放状态

this.$refs.Ref_audioPlayer.paused
  • true 为暂停
  • false 为播放

获取音频总时长

单位为秒s

this.$refs.Ref_audioPlayer.duration

获取播放进度

单位为秒s

this.$refs.Ref_audioPlayer.currentTime

开始播放

this.$refs.Ref_audioPlayer.play();

暂停播放

this.$refs.Ref_audioPlayer.pause();

改变播放进度–前进、后退

    // 原创面板——前进、后退——改变当前播放位置
    move(val) {
      this.$refs.Ref_audioPlayer.currentTime += val;
      this.$refs.Ref_audioPlayer.play();
    },

重头开始播放

this.$refs.Ref_audioPlayer.currentTime = 0;
 this.$refs.Ref_audioPlayer.play();

audio标签的事件

通过监听事件实现

play:音频或视频文件已经就绪可以开始播放时触发

playing:音频或视频已开始播放时触发

ended:音频或视频文件播放完毕后触发

pause:音频或视频文件暂停时触发

ratechange:播放速度改变进触发

seeked:指示定位已结束时触发

seeking:正在进行指示定位时触发

timeupdate:播放位置改变时触发

volumechange:音量改变时触发

waiting:需要缓冲下一帧而停止时触发

loadstart:浏览器开始寻找指定的音频或视频

progress:浏览器正在下载指定的音频或视频

durationchange:音频或视频的时长已改变

loadedmetadata:音频或视频的元数据已加载

loadeddata:音频或视频的当前帧已加载,但没有足够数据播放下一帧

canplay:浏览器能够开始播放指定的音频或视频

canplaythrough:音频或视频能够不停顿地一直播放

progress:浏览器正在下载指定的音频或视频

abort:在音频或视频终止加载时触发

error:在音频或视频加载发生错误时触发

stalled:在浏览器尝试获取媒体数据,但数据不可用时触发

suspend:在音频或视频数据被阻止加载时触发

empted:在发生故障并且文件突然不可用时触发

play:音频或视频文件已经就绪可以开始播放时触发

playing:音频或视频已开始播放时触发

ended:音频或视频文件播放完毕后触发

pause:音频或视频文件暂停时触发

ratechange:播放速度改变进触发

seeked:指示定位已结束时触发

seeking:正在进行指示定位时触发

timeupdate:播放位置改变时触发

volumechange:音量改变时触发

waiting:需要缓冲下一帧而停止时触发

语音条

请参考

https://www.jianshu.com/p/11a6101d9656

目录
相关文章
|
2月前
|
API UED 容器
深入探索 Element UI:自定义滚动条与弹出层管理的技巧
在这篇博客中,我们将深入探讨 Element UI 中的自定义滚动条及弹出层管理技巧。文章详细介绍了 el-scrollbar 组件的使用和参数设置,以及 PopupManager 如何有效管理弹出层的 z-index。我们还将探讨如何实现灵活的全屏组件,利用 vue-popper 创建自定义弹出层,最后介绍 ClickOutside 指令的用法。这些高级技巧将帮助你提升 Element UI 应用程序的用户体验与交互灵活性。
272 1
深入探索 Element UI:自定义滚动条与弹出层管理的技巧
|
3月前
|
JavaScript
Ant Design Vue UI框架的基础使用,及通用后台管理模板的小demo【简单】
这篇文章介绍了如何使用Ant Design Vue UI框架创建一个简单的后台管理模板,包括创建Vue项目、安装和使用ant-design-vue、以及编写后台管理通用页面的代码和样式。
Ant Design Vue UI框架的基础使用,及通用后台管理模板的小demo【简单】
|
2月前
|
JavaScript 索引
Vue开发中Element UI/Plus使用指南:常见问题(如Missing required prop: “value“)及中文全局组件配置解决方案
Vue开发中Element UI/Plus使用指南:常见问题(如Missing required prop: “value“)及中文全局组件配置解决方案
156 0
|
4月前
|
开发者 C# Android开发
明白吗?Xamarin与Native的终极对决:究竟哪种开发方式更适合您的项目需求,让我们一探究竟!
【8月更文挑战第31天】随着移动应用开发的普及,开发者面临多种技术选择。本文对比了跨平台解决方案Xamarin与原生开发方式的优势与劣势。Xamarin使用C#进行跨平台开发,代码复用率高,可大幅降低开发成本;但因基于抽象层,可能影响性能。原生开发则充分利用平台特性,提供最佳用户体验,但需维护多套代码库,增加工作量。开发者应根据项目需求、团队技能和预算综合考量,选择最适合的开发方式。
130 0
|
6月前
|
网络协议 Android开发 数据安全/隐私保护
Android手机上使用Socks5全局代理-教程+软件
Android手机上使用Socks5全局代理-教程+软件
5007 2
|
7月前
|
监控 安全 Android开发
【新手必读】Airtest测试Android手机常见的设置问题
【新手必读】Airtest测试Android手机常见的设置问题
212 0
|
7月前
|
XML Java Android开发
Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信)
Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信)
471 0
|
7月前
|
Web App开发 前端开发 网络安全
前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
【2月更文挑战第21天】前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
110 1
前端分析工具之 Charles 录制 Android/IOS 手机的 https 应用
|
7月前
|
存储 数据库 Android开发
Android实现手机内存存储功能
Android实现手机内存存储功能
67 2
|
7月前
|
网络协议 安全 Linux
如何使用Android手机通过JuiceSSH远程访问本地Linux服务器
如何使用Android手机通过JuiceSSH远程访问本地Linux服务器