npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tanzhenxing/zx-audio

v1.0.6

Published

zx-audio组件

Readme

zx-audio 音频播放组件

介绍

zx-audio 是一个功能强大的uni-app音频播放组件,支持普通音频播放和背景音频播放模式。该组件提供了丰富的配置选项和事件,使音频播放功能的实现变得简单高效。

特性

  • 支持普通音频播放和背景音频播放
  • 提供完善的音频控制API
  • 自动处理音频状态和生命周期
  • 支持音频加载状态监听
  • 支持播放进度控制
  • 支持音量和播放速率调节
  • 错误处理机制完善

安装和引入

在项目中引入组件

将组件复制到您的项目组件目录下,然后在需要使用的页面中引入:

<script setup>
import ZxAudio from '@/components/zx-audio/zx-audio.vue';
</script>

<template>
  <ZxAudio ref="audioRef" :src="audioSrc" />
</template>

属性说明

| 属性名 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | src | String | '' | 音频资源地址 | | startTime | Number | 0 | 开始播放的位置(单位:秒) | | autoplay | Boolean | false | 是否自动播放 | | loop | Boolean | false | 是否循环播放 | | obeyMuteSwitch | Boolean | true | 是否遵循系统静音开关 | | volume | Number | 0.8 | 音量,范围0-1 | | sessionCategory | String | 'playback' | 音频会话类别,可选值:'ambient'、'soloAmbient'、'playback' | | playbackRate | Number | 1.0 | 播放速率,范围0.5-2.0 | | title | String | '' | 音频标题,在背景音频模式下使用 | | coverImgUrl | String | '' | 封面图片URL,在背景音频模式下使用 | | singer | String | '' | 歌手名称,在背景音频模式下使用 | | useBackgroundAudio | Boolean | false | 是否使用背景音频播放模式(允许后台播放) |

sessionCategory 说明

  • ambient: 不中止其他声音播放,不能后台播放,静音后无声音
  • soloAmbient: 中止其他声音播放,不能后台播放,静音后无声音
  • playback: 中止其他声音,可以后台播放,静音后有声音

事件说明

| 事件名 | 说明 | 返回值 | | --- | --- | --- | | onCanplay | 音频可以播放时触发 | duration (音频时长) | | onPlay | 音频开始/继续播放时触发 | - | | onPause | 音频暂停时触发 | - | | onStop | 音频停止时触发 | - | | onEnded | 音频自然播放结束时触发 | - | | onTimeUpdate | 播放进度变化时触发 | { duration, currentTime, progress } | | onError | 播放错误时触发 | error对象 | | onWaiting | 音频加载中时触发 | - | | onSeeking | 音频跳转中时触发 | - | | onSeeked | 音频跳转完成时触发 | - | | onLoading | 音频加载状态变化时触发 | loading状态(Boolean) | | onNext | 背景音频播放下一首时触发(仅背景音频模式) | - | | onPrev | 背景音频播放上一首时触发(仅背景音频模式) | - |

方法说明

通过ref获取组件实例,可以调用以下方法:

| 方法名 | 说明 | 参数 | | --- | --- | --- | | play | 开始播放 | - | | pause | 暂停播放 | - | | stop | 停止播放 | - | | seek | 跳转到指定时间 | time (单位:秒) | | destroy | 销毁音频实例 | - | | change | 更改音频源并应用设置 | - | | setProgress | 设置播放进度 | progress (0-100的数值) | | togglePlay | 切换播放/暂停状态 | - | | getAudioData | 获取当前音频数据 | - | | setVolume | 设置音量 | volume (0-1的数值) | | setSrc | 切换音频源 | src (音频地址), autoplay (是否自动播放) |

使用示例

基本使用

<template>
  <view class="container">
    <zx-audio
      ref="audioRef"
      :src="audioSrc"
      :autoplay="false"
      :loop="false"
      :volume="0.8"
      @onCanplay="onCanplay"
      @onPlay="onPlay"
      @onPause="onPause"
      @onTimeUpdate="onTimeUpdate"
      @onEnded="onEnded"
      @onError="onError"
    />
    
    <view class="controls">
      <button @click="handlePlay">{{ isPaused ? '播放' : '暂停' }}</button>
      <button @click="handleStop">停止</button>
      
      <view class="progress-bar">
        <slider 
          :value="progress" 
          :min="0" 
          :max="100" 
          @change="handleProgressChange" 
        />
        <text>{{ formatTime(currentTime) }} / {{ formatTime(duration) }}</text>
      </view>
      
      <view class="volume-control">
        <text>音量:</text>
        <slider 
          :value="volume * 100" 
          :min="0" 
          :max="100" 
          @change="handleVolumeChange" 
        />
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue';
import ZxAudio from '@/components/zx-audio/zx-audio.vue';

const audioRef = ref(null);
const audioSrc = ref('https://red-education.wufu-app.com/upload/20211123/481d6b654e52961d43c454336a775145.mp3');
const isPaused = ref(true);
const progress = ref(0);
const currentTime = ref(0);
const duration = ref(0);
const volume = ref(0.8);

// 事件处理
const onCanplay = (dur) => {
  duration.value = dur;
  console.log('音频可以播放,时长:', dur);
};

const onPlay = () => {
  isPaused.value = false;
  console.log('音频开始播放');
};

const onPause = () => {
  isPaused.value = true;
  console.log('音频暂停');
};

const onTimeUpdate = (data) => {
  currentTime.value = data.currentTime;
  duration.value = data.duration;
  progress.value = data.progress;
};

const onEnded = () => {
  isPaused.value = true;
  console.log('播放结束');
};

const onError = (err) => {
  console.error('播放错误', err);
};

// 控制方法
const handlePlay = () => {
  if (isPaused.value) {
    audioRef.value.play();
  } else {
    audioRef.value.pause();
  }
};

const handleStop = () => {
  audioRef.value.stop();
  isPaused.value = true;
};

const handleProgressChange = (e) => {
  const value = e.detail.value;
  audioRef.value.setProgress(value);
};

const handleVolumeChange = (e) => {
  const value = e.detail.value / 100;
  volume.value = value;
  audioRef.value.setVolume(value);
};

// 格式化时间
const formatTime = (time) => {
  if (!time) return '00:00';
  const minutes = Math.floor(time / 60);
  const seconds = Math.floor(time % 60);
  return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
};
</script>

背景音频播放示例

<template>
  <view class="container">
    <zx-audio
      ref="bgAudioRef"
      :src="audioInfo.src"
      :title="audioInfo.title"
      :coverImgUrl="audioInfo.coverImgUrl"
      :singer="audioInfo.singer"
      :useBackgroundAudio="true"
      @onPlay="onPlay"
      @onPause="onPause"
      @onTimeUpdate="onTimeUpdate"
      @onEnded="onEnded"
    />
    
    <view class="music-player">
      <image :src="audioInfo.coverImgUrl" class="cover-image" />
      <view class="info">
        <text class="title">{{ audioInfo.title }}</text>
        <text class="singer">{{ audioInfo.singer }}</text>
      </view>
      
      <view class="progress-bar">
        <text>{{ formatTime(currentTime) }}</text>
        <slider 
          :value="progress" 
          :min="0" 
          :max="100" 
          @change="handleProgressChange" 
        />
        <text>{{ formatTime(duration) }}</text>
      </view>
      
      <view class="controls">
        <button @click="playPrev">上一首</button>
        <button @click="handlePlay" class="play-btn">
          {{ isPaused ? '播放' : '暂停' }}
        </button>
        <button @click="playNext">下一首</button>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue';
import ZxAudio from '@/components/zx-audio/zx-audio.vue';

const bgAudioRef = ref(null);
const isPaused = ref(true);
const progress = ref(0);
const currentTime = ref(0);
const duration = ref(0);
const currentIndex = ref(0);

// 播放列表
const playlist = [
  {
    src: 'https://red-education.wufu-app.com/upload/20211123/481d6b654e52961d43c454336a775145.mp3',
    title: '走进新时代',
    singer: '群星',
    coverImgUrl: 'https://red-education.wufu-app.com/upload/20211123/da546a455fe35fd0c510a332f245e201.png'
  },
  {
    src: 'https://red-education.wufu-app.com/upload/20211123/5abc7bc76fb3958e22e2906d206f7c3a.mp3',
    title: '游击队之歌',
    singer: '群星',
    coverImgUrl: 'https://red-education.wufu-app.com/upload/20211123/0cb8673254484ee7d90cd9598eadd2ac.png'
  },
  {
    src: 'https://red-education.wufu-app.com/upload/20211123/e32d0fcda506700a94e23ec9dff7fee9.mp3',
    title: '咱当兵的人',
    singer: '群星',
    coverImgUrl: 'https://red-education.wufu-app.com/upload/20211123/da546a455fe35fd0c510a332f245e201.png'
  }
];

const audioInfo = reactive(playlist[currentIndex.value]);

// 事件处理
const onPlay = () => {
  isPaused.value = false;
};

const onPause = () => {
  isPaused.value = true;
};

const onTimeUpdate = (data) => {
  currentTime.value = data.currentTime;
  duration.value = data.duration;
  progress.value = data.progress;
};

const onEnded = () => {
  playNext();
};

// 控制方法
const handlePlay = () => {
  if (isPaused.value) {
    bgAudioRef.value.play();
  } else {
    bgAudioRef.value.pause();
  }
};

const handleProgressChange = (e) => {
  const value = e.detail.value;
  bgAudioRef.value.setProgress(value);
};

const playNext = () => {
  currentIndex.value = (currentIndex.value + 1) % playlist.length;
  changeMusic();
};

const playPrev = () => {
  currentIndex.value = (currentIndex.value - 1 + playlist.length) % playlist.length;
  changeMusic();
};

const changeMusic = () => {
  Object.assign(audioInfo, playlist[currentIndex.value]);
  setTimeout(() => {
    bgAudioRef.value.change();
    bgAudioRef.value.play();
  }, 50);
};

// 格式化时间
const formatTime = (time) => {
  if (!time) return '00:00';
  const minutes = Math.floor(time / 60);
  const seconds = Math.floor(time % 60);
  return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
};
</script>

<style>
.music-player {
  padding: 20px;
}
.cover-image {
  width: 200px;
  height: 200px;
  border-radius: 8px;
  margin: 0 auto 20px;
  display: block;
}
.info {
  text-align: center;
  margin-bottom: 20px;
}
.title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 5px;
}
.singer {
  font-size: 14px;
  color: #666;
}
.progress-bar {
  display: flex;
  align-items: center;
  margin: 20px 0;
}
.progress-bar slider {
  flex: 1;
  margin: 0 10px;
}
.controls {
  display: flex;
  justify-content: space-around;
}
.play-btn {
  width: 100px;
}
</style>

注意事项

  1. 在App平台使用背景音频模式时,需要在 manifest.json 中配置:

    • iOS:在 app-plus -> distribute -> ios 节点下添加 "UIBackgroundModes":["audio"]
    • Android:默认不会在通知栏显示音量控制,需要在插件市场下载相关插件
  2. 在小程序平台使用背景音频模式时,需要在 manifest.json 中对应小程序节点下添加 "requiredBackgroundModes": ["audio"]

  3. 不同平台可能存在部分API差异,请根据实际情况调整使用方式

API参考