这微风不像那些壮志凌云的风,它只是轻轻地吹过,带走夏日的炎热,带来一丝凉爽。就像我少年时在炎热的夏天里寻找的穿堂风,低调而实用

前不久有大佬询问一个,微信小程序陪玩树洞列表主播语音播放,支持点击其他暂停当前语音的问题;
正常我以为audio即可,动态列表无法就是循环audio 之后做点击事件;而我们阅读文档发现,微信小程序平台自基础库 1.6.0 版本开始,不再维护 audio 组件,推荐使用API方式而不是组件方式来播放音频。API见 uni.createInnerAudioContext 替代(为了方便使用uni-app做演示)

效果预览

案例代码
<template>
<view>
<!-- 列表 -->
<view class="list-flex">
<view class="list-item" v-for="(item, index) in list" :key="index">
<image class="all-img" :src="item.covery" mode="aspectFill"></image>
<view class="list-top-left">
{{ item.tag }}
</view>
<view class="list-top-right list-top-female">
<image class="list-top-icon" src="/static/female.svg" mode="aspectFit"></image> 女
</view>
<view class="list-bottom">
<view class="list-bottom-title all-one-font">
{{ item.name }}
</view>
<view class="list-bottom-destc all-one-font">
{{ item.desrc }}
</view>
<div class="list-bottom-flex">
<view @tap.stop="playAudio(index)">
<view class="list-audio" v-if="isPlaying[index]">
<image class="list-audio-icon" src="/static/pause-one.svg" mode="aspectFit"></image>
<image class="list-audio-icon" src="/static/acoustic.svg" mode="aspectFit"></image>
</view>
<view class="list-audio" v-else>
<image class="list-audio-icon" src="/static/play-one.svg" mode="aspectFit"></image>
<image class="list-audio-icon" src="/static/acoustic.svg" mode="aspectFit"></image>
</view>
</view>
<view>
<span class="list-price-blod">{{item.price}}</span><span class="list-price">币/时</span>
</view>
</div>
</view>
</view>
</view>
<button @tap="dataAdd()">点击添加2条数据</button>
<view style="height: 100rpx;"></view>
</view>
</template>
<script>
export default {
data() {
return {
webSet: [], //基本配置
defaultIndex: 0,
topMuen: ['全部', '男', '女'],
// 音频上下文对象数组
audioContexts: [],
// 记录每个音频的播放状态
isPlaying: [],
list: [{
name: "往往",
tag: "王者荣耀",
desrc: "心有千千结,唯你能解",
audio: '/static/1.mp3',
price: '300',
covery: "https://pic.3gbizhi.com/uploadmark/20250224/b218884f1d8f6cae08bc74e955ff566c.webp",
}, {
name: "曦城摸",
tag: "树洞",
desrc: "遇见你,是我最美的意外",
audio: '/static/2.mp3',
price: '300',
covery: "https://pic.3gbizhi.com/uploads/20250221/4731730dfd28410cf6f4d86082cf669d.webp",
}, {
name: "呜呜",
tag: "CSGO",
desrc: "爱,让平凡的日子闪闪发光",
audio: '/static/3.mp3',
price: '300',
covery: "https://pic.3gbizhi.com/uploads/20250117/348682cf1d1f767ef29479549e71b35a.webp",
}]
}
},
onLoad(ops) {
// 初始化列表,可以在请求Api接口后执行
this.createAudioContexts();
},
methods: {
// 点击添加2条数据 模拟数据上拉加载
dataAdd() {
var adds = [{
name: "梓稀",
tag: "cf逆战",
desrc: "在你的怀抱里,我找到了归宿",
audio: '/static/4.mp3',
price: '300',
covery: "https://pic.3gbizhi.com/uploads/20250123/278517dcd2cd69358a04dce937360725.webp",
}, {
name: "郝总",
tag: "树洞",
desrc: "你的笑,是我抵御世间所有寒冷的暖阳",
audio: '/static/5.mp3',
price: '300',
covery: "https://pic.3gbizhi.com/uploads/20250117/3b4dda3e39ffa2171b0fc41b5a1c0698.webp",
}]
this.list = this.list.concat(adds);
this.createAudioContexts();
},
// 创建音频上下文对象
createAudioContexts() {
this.audioContexts = [];
this.isPlaying = new Array(this.list.length).fill(false);
this.list.forEach((item) => {
const audioContext = uni.createInnerAudioContext();
// 修改这里,从 item.audio 获取音频源
audioContext.src = item.audio ? item.audio : '';
// 监听音频播放事件
audioContext.onPlay(() => {
const index = this.list.indexOf(item);
this.isPlaying[index] = true;
});
// 监听音频暂停事件
audioContext.onPause(() => {
const index = this.list.indexOf(item);
this.isPlaying[index] = false;
});
// 监听音频停止事件
audioContext.onStop(() => {
const index = this.list.indexOf(item);
this.isPlaying[index] = false;
});
// 监听音频播放结束事件
audioContext.onEnded(() => {
const index = this.list.indexOf(item);
this.isPlaying[index] = false;
});
// 监听音频播放错误事件
audioContext.onError((res) => {
console.error('音频播放出错:', res.errMsg);
});
this.audioContexts.push(audioContext);
});
},
// 播放音频方法
playAudio(index) {
// 停止其他正在播放的音频
this.audioContexts.forEach((context, i) => {
if (i !== index && this.isPlaying[i]) {
context.stop();
}
});
// 控制当前点击的音频播放或暂停
const currentAudio = this.audioContexts[index];
if (this.isPlaying[index]) {
currentAudio.pause();
} else {
currentAudio.play();
}
},
},
onUnload() {
// 页面卸载时销毁所有音频上下文对象
this.audioContexts.forEach((context) => {
context.destroy();
});
},
}
</script>
<style>
.all-img {
height: 100%;
width: 100%;
}
/* 列表 */
.list-audio-icon {
height: 40rpx;
width: 40rpx;
margin-left: 4rpx;
}
.list-audio {
background-color: rgba(255, 255, 255, 0.61);
width: 140rpx;
height: 48rpx;
border-radius: 200rpx;
display: flex;
align-items: center;
}
.list-price-blod {
font-size: 30rpx;
font-weight: bold;
}
.list-price {
font-size: 24rpx;
margin-left: 5rpx;
}
.list-bottom-flex {
display: flex;
align-items: center;
justify-content: space-between;
width: calc(100% - 20rpx);
overflow: hidden;
color: #fff;
margin: 0 10rpx 20rpx 10rpx;
}
.list-bottom-title {
color: #fff;
margin: 10rpx;
}
.list-bottom-destc {
color: #fff;
font-size: 24rpx;
margin: 10rpx;
}
.list-bottom {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background: linear-gradient(to top, rgba(0, 0, 0, 0.86), rgba(255, 255, 255, 0));
border-radius: 20rpx;
}
.list-top-icon {
height: 26rpx;
width: 26rpx;
}
.list-top-left {
background: linear-gradient(90deg, #7c00ff, #7c04ff);
padding: 6rpx 20rpx;
border-top-left-radius: 20rpx;
border-bottom-right-radius: 20rpx;
position: absolute;
top: 0;
left: 0;
font-size: 24rpx;
color: #fff;
display: flex;
align-items: center;
}
.list-top-male {
background: linear-gradient(90deg, #56c2f4, #4ef3d2);
}
.list-top-female {
background: linear-gradient(90deg, #7a4adc, #f34dc7);
}
.list-top-right {
padding: 6rpx 20rpx;
border-top-right-radius: 20rpx;
border-bottom-left-radius: 20rpx;
position: absolute;
top: 0;
right: 0;
font-size: 24rpx;
color: #fff;
}
.list-item {
width: 49%;
height: 500rpx;
border-radius: 20rpx;
overflow: hidden;
position: relative;
margin-bottom: 20rpx;
}
.list-flex {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 20rpx;
}
</style>
源码下载
关注公众号回复“陪玩语音列表”下载