Vue3自定义封装音频播放器

news2024/11/15 17:38:16

🚀 本片主要讲解如何使用Vue3去封装一个音频播放器,以及解决在ios微信浏览器中 无法获取音频时长问题

一、效果图

在这里插入图片描述

二、解决在微信环境中ios无法获取音频时长问题

1、安装weixin-js-sdk

cnpm i weixin-js-sdk --save

2、使用,通过wx.ready中重新去加载音频资源

 wx.config({
  // 可无需配置配置相关参数
  debug: false,
  appId: '',
  timestamp: 1,
  nonceStr: '',
  signature: '',
  jsApiList: []
});
wx.ready(function () {
  audioInfo.audioObject.load()
});  

三、组件封装,整体代码

1、创建AudioCom.vue文件

<template>
  <div class="audio-box">
    <div class="action-box">
      <div class="actions">
        <van-slider
          :max="audioInfo.totalTime"
          bar-height="3"
          button-size="17"
          inactive-color="#F0F0F0"
          active-color="#ffd55a"
          v-model="audioInfo.timeNow"
          @change="onChange"
          :disabled="!audioInfo.status"
          @drag-start="dragState(true)"
          @drag-end="dragState(false)"
        >
          <template #button>
            <div class="custom-button" />
          </template>
        </van-slider>
      </div>
      <div class="time-row">
        <span>{{ getStringTime(audioInfo.timeNow) }}</span>
        <span>{{ getStringTime(audioInfo.totalTime) }}</span>
      </div>
    </div>
    <div class="play-control hover" @click="playOrPause" ontouchstart>
      <div v-if="!audioInfo.loading">
        <van-icon name="play" v-show="!audioInfo.status" />
        <van-icon name="pause" v-show="audioInfo.status" />
      </div>
      <van-loading v-else  color="#FF980F"/>
    </div>
  </div>
</template>

<script lang='ts' setup>
import { audioInit } from './index.hook'
const props = withDefaults(defineProps<{
  src?: string,
}>(), {
  src: ''
})

const { dragState, getStringTime, playOrPause, onChange, audioInfo } = audioInit(props)

</script>
<style lang="scss" scoped>
.audio-box {
  display: flex;
  width: 100%;
  align-items: center;
  margin-left: -10px;
  margin-top: 20px;
  .play-control {
    width: 62px;
    height: 62px;
    border-radius: 50%;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    margin-left: 6px;
    justify-content: center;
    border: 2px solid #FF980F;
    >div {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    i {
      font-size: 45px;
      color: #FF980F;
    }
  }
  .action-box {
    flex: 1;
    position: relative;
    min-width: 0;
    margin-top: 20px;
    .time-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 24px;
      color: #999999;
      margin-top: 20px;
      box-sizing: border-box;
      padding: 0 15px;
    }
    .actions {
      display: flex;
      align-items: center;
      >span {
        font-size: 22px;
        color: #838383;
      }
      :deep(.van-slider) {
        flex: 1;
        margin: 0 20px;
      }
    }
  }
}
.custom-button {
    width: 10px;
    height: 26px;
    color: #fff;
    font-size: 10px;
    line-height: 18px;
    text-align: center;
    background-color: #FF980F;
    border-radius: 100px;
}
</style>

2、创建index.hook.ts文件

import { reactive, watch } from 'vue'
import wx from 'weixin-js-sdk'

export const audioInit = (props: { src: string }) => {
  wx.config({
    // 配置信息, 即使不正确也能使用 wx.ready
    debug: false,
    appId: '',
    timestamp: 1,
    nonceStr: '',
    signature: '',
    jsApiList: []
  });
  const audioInfo: any = reactive({
    audioObject: null,
    timeNow: 0,
    totalTime: 1.5,
    status: false,
    isSlide: false,
    loading: false
  })
  const dragState = (bool: boolean) => {
    audioInfo.isSlide = bool;
  }
  const onChange = (value: number) => {
    audioInfo.audioObject.currentTime = value;
  }
  const playOrPause = () => {
    if (audioInfo.totalTime === 1.5 || audioInfo.totalTime === '00:00') {
      audioInfo.loading = true
      return
    }

    if (audioInfo.status) {
      audioInfo.audioObject.pause();
      audioInfo.status = false;
    } else {
      audioInfo.audioObject.play();
      audioInfo.status = true;
    }
  }
  const getStringTime = (time: any) => {
    if (time === 1.5 || isNaN(time)) {
      return "00:00"
    }
    let minute: number | string = parseInt(time / 60);
    if (minute < 10) {
      minute = `0${minute}`;
    }
    let second: number | string = parseInt(time % 60);
    if (second < 10) {
      second = `0${second}`;
    }
    return minute + ":" + second;
  }

  const resetState = () => {
    audioInfo.audioObject = null
    audioInfo.totalTime = 1.5
    audioInfo.timeNow = 0
    audioInfo.status = false
    audioInfo.isSlide = false
    audioInfo.loading = false
  }
  
  // 判断是否是ios环境
  const  is_iOS = () => {
    return /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent);
  }

  const createAudio = () => {
    audioInfo.audioObject = new Audio(props.src);
    audioInfo.audioObject.addEventListener(is_iOS() ? "loadedmetadata" : "loadeddata", function () {
      audioInfo.totalTime = parseInt(audioInfo.audioObject.duration);
      audioInfo.loading = false
    });
    audioInfo.audioObject.addEventListener("timeupdate", function () {
      let tempSecond = parseInt(audioInfo.audioObject.currentTime);
      if (audioInfo.timeNow != tempSecond && !audioInfo.isSlide) {
        audioInfo.timeNow = tempSecond;
      }
    });
    audioInfo.audioObject.addEventListener("ended", function () {
      audioInfo.status = false;
      audioInfo.timeNow = 0;
    });
    wx.ready(function () {
      audioInfo.audioObject.load()
    });
  }

  watch(() => props.src, (news) => {
    resetState()
    if (news) {
      createAudio()
    }
  }, {
    deep: true,
    immediate: true
  })
  return {
    dragState,
    getStringTime,
    playOrPause,
    onChange,
    audioInfo
  }
}

🚀🚀🚀🚀 大功告成 🚀🚀🚀🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/815255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CAS6.6源码解析】深入解析TGT和ST的唯一ID是怎样生成的-探究ID生成器的设计

CAS作为一款企业级中央认证服务系统&#xff0c;其票据的生成是非常重要的一环&#xff0c;在票据的生成中&#xff0c;有一个比较重要的点就是为票据生成唯一ID&#xff0c;本文将深入解析CAS系统中的TGT和ST的唯一ID是怎样生成的。 文章重点分析源码的过程&#xff0c;不想看…

W2NER详解

论文&#xff1a;https://arxiv.org/pdf/2112.10070.pdf 代码&#xff1a;https://github.com/ljynlp/W2NER 文章目录 W2NER介绍模型架构解码 源码介绍数据输入格式模型代码 参考资料 W2NER 介绍 W2NER模型&#xff0c;将NER任务转化预测word-word&#xff08;备注&#xff…

基于flask旅游大数据可视化分析推荐系统-计算机毕设 附源码10903

flask旅游大数据可视化分析推荐系统 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对旅游大…

味知香VS千味央厨,谁是预制菜新王?

夏日炎炎&#xff0c;预制菜赛道的下半场也硝烟弥漫&#xff0c;可谓“冰火两重天”。 预制菜赛道两大“玩家”&#xff1a;“预制菜第一股”味知香(605089.SH&#xff09;、“餐饮供应链第一股”千味央厨(001215.SZ)均于近日公布了2023年一季报&#xff0c;其业绩有所分化。 …

3D Web轻量化渲染开发工具HOOPS Communicator是什么?

HOOPS Communicator是Tech Soft 3D旗下的主流产品之一&#xff0c;具有强大的、专用的高性能图形内核&#xff0c;是一款专注于基于Web端的高级3D工程应用程序。由HOOPS Server和HOOPS Web Viewer两大部分组成&#xff0c;提供了HOOPS Convertrer、Data Authoring的模型转换和编…

考试系统对教育评估的作用和意义

随着现代教育的发展&#xff0c;考试系统已经成为评估学生学业水平的重要工具。考试系统通过量化学生的知识掌握程度、学术能力和解决问题的能力&#xff0c;为教育评估提供了客观的数据基础。 考试系统能够帮助学校和教育部门全面了解学生的学习状况。通过考试结果&#xff0…

2023东三省“深圳杯”A题全保姆论文讲解

A题 影响城市居民身体健康的因素分析 以心脑血管疾病、糖尿病、恶性肿瘤以及慢性阻塞性肺病为代表的慢性非传染性疾病&#xff08;以下简称慢性病&#xff09;已经成为影响我国居民身体健康的重要问题。随着人们生活方式的改变&#xff0c;慢性病的患病率持续攀升。众所周知&am…

C#winform顺序打包成安装项目(VS2022)

一、在打包之前 (VS中需要包括Microsoft visual studio installer projects扩展项目) 1、在vs中找到扩展>管理扩展>搜索 installer projects 进行扩展的下载 2、右键Application Folder >点击 Add>点击项目输出>点击确认后>旁边则会生成一个主输出的文 3、…

132个心理性格趣味测试ACCESS\EXCEL数据库

今天又遇到了一个心理测试的数据库&#xff0c;这个数据库在表结构的设置上很直观&#xff0c;属于那种好的数据库结构&#xff0c;共分三个表&#xff0c;一个是测试项目描述表、一个是测试题选项得分表、一个是根据得分区间解析表&#xff0c;表与表之间通过“question_id”字…

WIFI模块常见的三种接口类型

什么是WIFI接口&#xff1a; WIFI接口是用于让设备无线连接到网络的功能&#xff0c;使你的电脑、手机、平板等设备可以通过无线信号连接到互联网或局域网。 1.USB接口 USB接口是平时见得最多的一种接口了&#xff0c;用在wifi模块上&#xff0c;它是一种通用串行总线&#…

docker如何运行容器?

文章目录 1 容器操作1.1容器相关命令1.2 创建并运行一个容器docker命令解析nacos启动成功 访问进入容器&#xff0c;修改配置文件 总结 接上集 CentOS 7安装Docker https://blog.csdn.net/qq_39017153/article/details/131955100 1 容器操作 1.1容器相关命令 容器操作的命令如…

【客户案例】云联壹云助力某保险公司搭建公有云费用管理平台

客户介绍 客户成立于 1996 年 11 月&#xff0c;现已拥有逾 2000 名员工和 12000 名营销员&#xff0c;为 280 万客户提供专业的金融保险服务。在上海、北京、广东、浙江、江苏、四川、山东、福建、重庆、辽宁、天津、湖北、河北、湖南和陕西等地的 50 多个城市稳步发展&#…

激光雷达在辅助驾驶领域正在沦为“花拳绣腿”?

摘要&#xff1a; 激光雷达的优点显而易见&#xff0c;但如何结合算法发挥出激光雷达的优势&#xff0c;我想除了主机厂以外&#xff0c;激光雷达厂商也可以主动参与&#xff0c;主动探索先进的融合感知算法&#xff0c;向行业不断证明&#xff1a;我不是个“花瓶”。 激光雷达…

CMake简介

文章目录 为什么需要头文件为什么 C 需要声明头文件 - 批量插入几行代码的硬核方式头文件进阶 - 递归地使用头文件 CMake什么是编译器多文件编译与链接CMake 的命令行调用为什么需要库&#xff08;library&#xff09;CMake 中的静态库与动态库CMake 中的子模块子模块的头文件如…

进入NetApp FAS存储系统loader的三种方法

有时候需要在loader模式下对系统硬件做一些offline的诊断&#xff0c;但offline 对系统物理部件做诊断需要进入到loader模式&#xff0c;如何从一个正常运行的系统进入到loader模式呢&#xff1f; 第一种就是启动的时候看到CtrlC的提示&#xff0c;就可以顺利进入loader。 如…

网络工程毕设-----基于华为ensp搭建校园网

本实验用华为模拟器ensp搭建简单的校园网络&#xff0c;其中用到的技术有动态路由协议OSPF&#xff0c;静态路由配置&#xff0c;HTTP、DNS以及FTP服务器的配置&#xff0c;PNAT端口地址转换协议&#xff0c;MSTP多生成树协议&#xff0c;VLAN划分及配置IP地址划分及配置等! 选…

机器学习实战:Python基于EM期望最大化进行参数估计(十五)

文章目录 1. 前言1.1 EM的介绍1.2 EM的应用场景 2. 高斯混合模型估计2.1 导入函数2.2 创建数据2.3 初始化2.4 Expectation Step2.5 Maximization step2.6 循环迭代可视化 3. 多维情况4. 讨论 1. 前言 1.1 EM的介绍 &#xff08;Expectation-Maximization&#xff0c;EM&#…

实战案例:使用 Python 机器学习预测外卖送餐时间

现在的天气是一天比一天热&#xff0c;好多人周末休息在家的时候&#xff0c;就会选择点外卖&#xff0c;毕竟出去一趟又晒又热。 如果你太饿了&#xff0c;点餐太晚了&#xff0c;就可能去关注外卖员送餐到哪了&#xff0c;还有多少时间能送达。 这些信息在美团、饿了吗的Ap…

MapReduce原理剖析

一、基本介绍 MapReduce是Hadoop的核心&#xff0c;是Google提出的一个软件架构&#xff0c;用于大规模数据集&#xff08;大于1TB&#xff09;的并行运算。概念“Map&#xff08;映射&#xff09;”和“Reduce&#xff08;化简&#xff09;”&#xff0c;及他们的主要思想&am…

AWS 推出开源 AutoML 工具包“AutoGluon”

亚马逊网络服务最近推出了一个开源库&#xff0c;使开发人员只需几行代码即可在图像、文本或表格数据上实现深度学习模型。 AutoGluon 旨在成为一个易于使用且易于扩展的 AutoML 工具包&#xff0c;适合机器学习初学者和专家。它只需几行即可对深度学习模型进行原型设计;自动超…