原生uniapp 录音组件,复制就能用
代码部分
<template>
<view class="box">
<uni-popup ref="popup" :animation="true" :is-mask-click="false">
<view class="popup_box" @tap.stop = "closePop">
<view class="move">
<view v-if="btnStatus!==0" :class="btnStatus==3? 'move_center_clear': 'move_center'">
<view class="move_center_top">
<view class="move_center_item" v-for="(item,index) in 15" :key="index">
</view>
</view>
<view class="move_center_footer">
{{btnStatus==3? '松开手指,取消发送':"正在录音..."}}
</view>
</view>
</view>
<view :class=" btnStatus==0? 'footerBtn': btnStatus==1?'footerBtn_star':'footerBtn_move'">
<view class="footerBtn_chr" @touchend="end" @touchmove="move" @touchstart="start">
{{btnStatus==0? "按住说话":btnStatus==1? "说话中...": btnStatus==2? "松开手指发送录音": "上划取消"}}
</view>
</view>
<!-- <button @click="play(voicePath)">播放</button> -->
</view>
</uni-popup>
</view>
</template>
js部分
<script>
const recorderManager = uni.getRecorderManager()
const innerAudioContext = uni.createInnerAudioContext()
innerAudioContext.autoplay = true
export default {
name: "sound",
props: {
maskShow: false, //遮罩层
},
data() {
return {
recordFlg: true, //录音锁
btnStatus: 0, //按钮状态
audioDuration: "",
voicePath: "", //音频本地路径
timer: null, //定时器
num: 0, //录音时长
}
},
watch: {
maskShow: {
// 每个属性值发生变化就会调用这个函数
handler(newVal, oldVal) {
console.log(newVal, oldVal, "监听");
if (newVal === true) {
this.$refs.popup.open('center')
} else {
this.$refs.popup.close()
}
},
// 立即处理 进入页面就触发
// immediate: true,
// 深度监听 属性的变化
// deep: true
},
},
created() {
console.log("888");
// 为了防止苹果手机静音无法播放
uni.setInnerAudioOption({
obeyMuteSwitch: false
})
let that = this;
recorderManager.onStop(function(res) {
// 解决第一次录音,挂实例挂载问题
that.$nextTick(() => {
console.log('recorder stop' + JSON.stringify(res));
that.audioDuration = res.duration;
that.voicePath = res.tempFilePath;
})
});
},
methods: {
// 点击关闭遮罩层
closePop() {
this.$refs.popup.close()
this.$emit("emitCheck", false)
},
start() {
// 限制时长
this.timer = setInterval(() => {
this.num++
console.log("num", this.num);
}, 1000)
console.log("手指按下");
this.btnStatus = 1
// 暂停播放
// innerAudioContext.stop()
recorderManager.start({
//时长5分钟,单位毫秒
duration: 300000
});
this.recordFlg = true
},
move(e) {
if (Math.abs(e.touches[0].pageY) < 650 && Math.abs(e.touches[0].pageY) > 550) {
this.btnStatus = 2
} else if (Math.abs(e.touches[0].pageY) < 550) {
this.btnStatus = 3
} else {
this.btnStatus = 1
}
},
end() {
clearInterval(this.timer)
this.btnStatus = 0
recorderManager.stop();
console.log(this.voicePath, "888");
// 异步,解决录音结束后,路径没赋值就传值,导致的路径为空
setTimeout(() => {
let obj = {
status: false,
path: [{
src: this.voicePath,
switchStatus: false,
soundTime: this.num
}]
}
this.$emit("emitCheck", obj)
this.num = 0
}, 500)
console.log("手指松开", this.voicePath);
},
// play(value){
// console.log("播放");
// // innerAudioContext.src = value;
// innerAudioContext.play();
// },
// 删除本地录音文件
// del(){
// uni.getSavedFileList({
// success: function (res) {
// if (res.fileList.length > 0) {
// uni.removeSavedFile({
// filePath: res.fileList[0].filePath,
// complete: function (res) {
// console.log(res);
// }
// });
// }
// }
// });
// }
}
}
</script>
css部分
<style lang="scss" scoped>
@keyframes load {
0% {
height: 10%;
}
50% {
height: 100%;
}
100% {
height: 10%;
}
}
// 取消发送
.move_center_footer {
margin-top: 20rpx;
font-size: 24rpx;
color: #666;
}
.move_center_top {
height: 40rpx;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
.move_center_item {
display: block;
background: #333333;
width: 1px;
height: 10%;
margin: 0 6rpx;
float: left;
}
.move_center_item:nth-child(1) {
animation: load 2.5s 1.4s infinite linear;
}
.move_center_item:nth-child(2) {
animation: load 2.5s 1.2s infinite linear;
}
.move_center_item:nth-child(3) {
animation: load 2.5s 1s infinite linear;
}
.move_center_item:nth-child(4) {
animation: load 2.5s 0.8s infinite linear;
}
.move_center_item:nth-child(5) {
animation: load 2.5s 0.6s infinite linear;
}
.move_center_item:nth-child(6) {
animation: load 2.5s 0.4s infinite linear;
}
.move_center_item:nth-child(7) {
animation: load 2.5s 0.2s infinite linear;
}
.move_center_item:nth-child(8) {
animation: load 2.5s 0s infinite linear;
}
.move_center_item:nth-child(9) {
animation: load 2.5s 0.2s infinite linear;
}
.move_center_item:nth-child(10) {
animation: load 2.5s 0.4s infinite linear;
}
.move_center_item:nth-child(11) {
animation: load 2.5s 0.6s infinite linear;
}
.move_center_item:nth-child(12) {
animation: load 2.5s 0.8s infinite linear;
}
.move_center_item:nth-child(13) {
animation: load 2.5s 1s infinite linear;
}
.move_center_item:nth-child(14) {
animation: load 2.5s 1.2s infinite linear;
}
.move_center_item:nth-child(15) {
animation: load 2.5s 1.4s infinite linear;
}
}
.box {
.popup_box {
height: 100vh;
width: 100vw;
position: relative;
// 取消录音区域
.move {
width: 100%;
position: absolute;
left: 0;
bottom: 450rpx;
display: flex;
justify-content: center;
align-items: center;
.move_center_clear {
width: 40%;
height: 200rpx;
border-radius: 50rpx;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background: rgba(250, 83, 83, .5);
}
.move_center {
width: 40%;
height: 200rpx;
background: rgba(149, 234, 108, .5);
border-radius: 50rpx;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
}
// 底部按钮
.footerBtn {
padding: 20rpx 20rpx;
width: 100%;
position: absolute;
left: 0;
bottom: 60rpx;
.footerBtn_chr {
width: 100%;
height: 96rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
border-radius: 16rpx;
background-image: linear-gradient(to right, #dfbe9b 0%, #f3dfc9 100%);
color: #986546;
transition: all 0.3s;
}
}
.footerBtn_star {
width: 100%;
position: absolute;
left: 0;
bottom: 0rpx;
.footerBtn_chr {
width: 100%;
height: 250rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
border-radius: 140rpx 140rpx 0 0;
background: rgba(218, 227, 232, .8);
color: #666;
transition: all 0.3s;
}
}
.footerBtn_move {
width: 100%;
position: absolute;
left: 0;
bottom: 0rpx;
.footerBtn_chr {
width: 100%;
height: 250rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
border-radius: 140rpx 140rpx 0 0;
background: rgba(51, 51, 51, .5);
color: #dae3e8;
transition: all 0.3s;
}
}
}
}
</style>
使用
<!-- maskShow决定遮罩层是否显示 / @emitCheck自定义事件,用来接收组件返回值 -->
<sound :maskShow="footerList[1].status" @emitCheck="footerCheck"></sound>
借鉴
本来找的是另一个博主的代码样式,但是发现他的代码会导致ios微信小程序死机,研究一下午没解决,索性仿着写了一个,
那个博主的文章地址
版权声明:本文为qq_43513271原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。