uniapp:仿微信发送音频,录制音频。

文章展示了如何在Vue.js应用中创建一个子组件chatAudio,利用uni.getRecorderManager进行音频录制。当用户长按时,会弹出录制界面,用户可以录制最长60秒的音频。松开手指时,如果在删除区域内则取消录制,否则发送音频。子组件与父组件间通过props进行通信,监听音频录制的状态并触发相应的操作。
摘要由CSDN通过智能技术生成

在这里插入图片描述
在这里插入图片描述
uni.getRecorderManager()音频管理

1.创建子组件chatAudio.vue

<template>
	<view class="chatAudio">
		<view class="audioPlay" v-if="show">
			<view class="content">
				<!-- 录制中动图,底色变化 -->
				<view class="gif" :class="{'red':closeShow}">
					<image src="../../static/img/33.gif" mode=""></image>
				</view>
				<view class="close">
					<!-- ×号 颜色变化-->
					<image src="../../static/img/32.png" mode="" v-if="!closeShow"></image>
					<image src="../../static/img/28.png" mode="" v-if="closeShow"></image>
				</view>
				<view class="bom">
					<text v-if="!closeShow">松开 发送</text>
					<text v-if="closeShow">松开 取消</text>
					
					<!-- 底图颜色变化 -->
					<image src="../../static/img/30.png" mode="" v-if="!closeShow"></image>
					<image src="../../static/img/31.png" mode="" v-if="closeShow"></image>
					
					<!-- 计时器 -->
					<view class="times">
						<u-circle-progress active-color="#6C9FEB" :percent="times" bg-color="" width="140" border-width="7"></u-circle-progress>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>
<script>
	const recorderManager = uni.getRecorderManager();
	const innerAudioContext = uni.createInnerAudioContext();
	innerAudioContext.autoplay = true;
	export default {
		name: 'chatAudio',
		props: {
			audioShow: {
				type: Boolean,
				default: false
			},
			audioXY: {
				type: Object,
			},
			audioTouchendShow: {
				type: Boolean,
				default: false
			},
		},
		watch: {
			// audioShow:true录制界面显示,开始录音,false关闭。
			audioShow(e, oldVal) {
				if(e){
					console.log('开始录音')
					this.status = 0;
					this.audioSrc = '';
					this.number = 1;
					this.show = true;
					
					// 计算录制时长,>=60 录制结束
					this.times = 1;
					this.timesInt = setInterval(() => {
						this.times ++;
						console.log(this.times)
						if(this.times>= 60){
							clearInterval(this.timesInt);
							this.closeShow = false;
							recorderManager.stop();
							console.log('结束录制');
						}
					}, 1000);
					
					// 开始录制
					recorderManager.start();
					
					// 获取关闭按钮.close在屏幕中的位置信息
					this.$nextTick(()=>{
						let close = uni.createSelectorQuery().select(".close");
						close.boundingClientRect((data)=> {
							this.dom = data;
						}).exec()
					})
				}else{
					this.show = false;
				}
			},
			// 手指在屏幕中的位置,判断是否:录制中/删除
			audioXY(e){
				let x = e.x;
				let y = e.y;
				let left = this.dom.left;
				let top = this.dom.top;
				if(x>left && x<left+this.dom.width && y>top && y<top+this.dom.height){
					this.closeShow = true;
				}else{
					this.closeShow = false;
				}
			},
			// 手指结束触摸,通知父组件关闭弹窗,根据this.closeShow类型,判断是取消还是发送
			audioTouchendShow(e){
				this.$emit('closeAudioShow')
				if(this.number == 1){
					this.number++;
					if(this.closeShow){
						console.log('取消录制')
						clearInterval(this.timesInt);
						this.closeShow = false;
						recorderManager.stop();
					}else{
						console.log('发送音频');
						clearInterval(this.timesInt);
						this.closeShow = false;
						recorderManager.stop();
						this.status = 1;
					}
				}
			}
		},
		data() {
			return {
				show:false, // 弹窗
				closeShow:false, // 正常/删除
				winSize:{},
				dom:{}, // 删除按钮位置
				
				times:1, // 计时器
				timesInt:null, // 计时器
				status:0, //0录制中,1录制结束。
				number:1,
			}
		},
		mounted() {
			// 录音停止事件,会回调文件地址,如果status == 1,上传音频,并通知父组件发送音频信息
			recorderManager.onStop((res)=> {
				console.log(res)
				this.audioSrc = res.tempFilePath;
				if(this.status == 1){
					this.upload(this.audioSrc, 'audio');
				}
			});
			uni.getSystemInfo({
				success: (res) => {
					this.winSize = {
						"witdh": res.windowWidth,
						"height": res.windowHeight
					}
				}
			})
		},
		methods: {
			// 上传音频,并发送
			upload(file, type) {
				this.$uploadImage('/api/***', file).then(res => {
					if (res.code == 1) {
						this.$emit('submit',type,res.data.url)
					}
				})
			},
		},
	}
</script>
<style lang="scss" scoped>
	.chatAudio {
		.audioPlay{
			width: 750rpx;
			min-height: 100vh;
			position: fixed;
			left: 0;
			top: 0;
			z-index: 999;
			display: flex;
			align-items: center;
			justify-content: center;
			background: rgba(0, 0, 0, .8);
			text-align: center;
			.content{
				position: absolute;
				left: 0;
				bottom: 100rpx;
				.gif{
					width: 364rpx;
					height: 172rpx;
					background: #6C9FEB;
					border-radius: 32rpx;
					margin: auto;
					display: flex;
					align-items: center;
					justify-content: center;
					transition: all .5s;
					uni-image{
						width: 160rpx;
						height: 48rpx;
					}
				}
				.red{
					background-color: #FB5353;
				}
				.close{
					margin: 176rpx auto 42rpx;
					width: 132rpx;
					height: 132rpx;
					uni-image{
						width: 132rpx;
						height: 132rpx;
					}
				}
				.bom{
					position: relative;
					.times{
						position: absolute;
						left: 50%;
						top: 125rpx;
						margin-left: -70rpx;
					}
					uni-image{
						width: 750rpx;
						height: 254rpx;
						margin-top: 26rpx;
					}
					uni-text{
						font-size: 28rpx;
						color: #9E9E9E;
					}
				}
				
			}
		}
	}
</style>

2.父组件

<template>
	<view>
		<view class="footer">
			<!--
				@longpress:长按元素,弹出弹窗。
				@touchmove:手指触摸元素后移动,获取手指在屏幕中的位置。
				@touchend:手指结束触摸元素,判断是否结束录制音频
			-->
			<view 
				@longpress="audioShow = true" 
				@touchmove.stop.prevent="audioTouchmove"
				@touchend.stop.prevent="audioTouchendShow = true">
				<text>按住 说话</text>
			</view>
		</view>
		
		<!--
				@submit:通知父组件,发送消息内容。
				audioXY:手指在屏幕中的位置信息。
				audioShow:是否弹出子组件
				audioTouchendShow:是否结束录制
				closeAudioShow:子组件通知父组件,结束录制,
			-->
		<chatAudio 
			@submit="submit" 
			:audioXY="audioXY" 
			:audioShow="audioShow" 
			:audioTouchendShow="audioTouchendShow" 
			@closeAudioShow="audioTouchendShow = false,audioShow = false">
		</chatAudio>
	</view>
	
</template>
<script>
	export default {
		data() {
			return {
				audioShow:false,// 录制音频弹窗
				audioTouchendShow:false,// 是否结束录制音频
			}
		},
		methods:{
			// 录音长按
			audioTouchmove(e){
				let x = e.changedTouches[0].clientX;
				let y = e.changedTouches[0].clientY;
				this.audioXY = {
					x:x,
					y:y
				}
			},
			// 发送
			submit(type,url){
			
			}
		}
	}
</script>
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值