微信小程序实现长按录音,上滑删除,抬起发送

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

因工作需要,开发录音功能,实现长按录制语音,4秒后自动停止,松开上传,使用了uview的圆形进度条来实现录制中的音阶动效,

一、getRecorderManager

获取全局唯一的录音管理器 RecorderManager

二、实现方法

代码如下:

html

<template>
	<view class="tape-module">
		<button class="record-btn flex-center" @longtap="recordingStatusBtn" @touchend="touchendBtn()"
			@touchmove="handleTouchMove" @touchstart="recordingStatusBtn">
			<text
				v-if="recordingStatus == 1 || recordingStatus == 5 || recordingStatus == 6 || recordingStatus == 7">按住开始录制</text>
			<text v-if="recordingStatus == 2">说话中</text>
			<text v-if="recordingStatus == 4">上传中...</text>
		</button>
		<view class="cancel" v-if="delShow">
			取消 上传
		</view>
		<view :class="'ly-close flex-center ' + (delShow ? 'select' : '')"  @tap="delBtn" v-if="recordingStatus != 3">
			<text class="iconfont icon-guanbi"></text>
		</view>
		<view
			:class="'tape-box flex-center ' + (recordingStatus == 2 ? 'column' : (recordingStatus == 4 || recordingStatus == 5) ? 'tape-error' : '')"
			v-if="!delShow">
			<view class="tape-tips" v-if="recordingStatus == 1">
				请按住下方按钮开始录制
			</view>
			<block v-if="recordingStatus == 2">
				<view class="u-press">
					<u-circle-progress inactive-color="#06AD56" width="100" border-width="6" active-color="#ffffff"
						:percent="tapePress" duration="4500" bg-color="transparent">
						<view class="prompt-loader">
							<view class="em" v-for="(item,index) in 5" :key="index"></view>
						</view>
					</u-circle-progress>
				</view>
				<view class="tape-title">
					正在录制一段您的专属人声片段
				</view>
			</block>
			<view class="succ-title" v-if="recordingStatus == 3">
				录制成功
			</view>
			<view class="error-title" v-if="recordingStatus == 5">
				您说话的时间太短了<br>重新录入
			</view>
			<view class="error-title" v-if="recordingStatus == 4">
				内容存在敏感信息<br>请重新上传
			</view>
		</view>
	</view>


</template>

2.js代码逻辑

<script>
	import uCircleProgress from "../../uni_modules/uview-v1_1/components/u-circle-progress/u-circle-progress.vue";
	const recorderManager = uni.getRecorderManager()
	var percentTime = null
	var uploadLyTime = null
	export default {
		components: {
			uCircleProgress,
		},
		data() {
			return {
				recordingStatus: 1, // 1按住说话 2说话中 3 录制成功 4敏感 5时间太短 
				delShow: false, // 删除提示框显示隐藏
				duration: 4000, //录音最大值ms 4秒
				url: '', //音频路径
				startPoint: {}, //记录录音开始点信息
				lock: true,
				tapePress: 0
			}
		},
		onLoad(options) {
			recorderManager.onStop((res) => {
				clearInterval(uploadLyTime)
				uploadLyTime = null
				this.tapePress = 100
				if (!this.lock) {
					if (res.duration > 3000 && res.duration < 5000) {
						//进入上传保存方法
						this.recordingStatus = 3;
						this.url = res.tempFilePath
						// this.saveVideo(res.tempFilePath)
					} else {
						this.recordingStatus = 5
					}
				}
			})
		},
		methods: {
			saveVideo(data) {
				uni.uploadFile({
					url: '敏感校验接口',
					filePath: data,
					name: 'file',
					success(res) {
						if (res.data.code == '0000') {
							this.recordingStatus = 3
							setTimeout(() => {
								this.recordingStatus = 1
							}, 1000)

						} else {
							this.recordingStatus = 4
							setTimeout(() => {
								this.recordingStatus = 1
							}, 1000)
						}
					},
					fail(error) {
						uni.showToast({
							title: '系统开小差了',
							icon: 'none'
						})
					}
				})
			},
			recordingStatusBtn(e) {
				this.startPoint = e.touches[0];
				this.recordingStatus = 2;
				const options = {
					duration: this.duration,
					format: 'mp3',
				}
				recorderManager.start(options);
				this.tapePress = 0
				uploadLyTime = setInterval(() => {
					this.tapePress = this.tapePress + 25
				}, 1000)
				this.lock = false;
			},
			touchendBtn() {
				recorderManager.stop(); //结束录音
			},
			handleTouchMove(e) {
				let moveY = e.touches[0].clientY - this.startPoint.clientY; //移动距离
				let moveX = e.touches[0].clientX - this.startPoint.clientX;
				console.log(moveY)
				if (moveY < -100) {
					this.delShow = true
					this.lock = true
					this.recordingStatus = 1
				} else {
					this.delShow = false
					this.lock = false
				}
			},
			delBtn() {
				this.delShow = false
				this.recordingStatus = 1
			}
		}



	}
</script>

3.css样式


<style scoped lang="less">
	.tape-module {
		width: 100%;
		height: 100vh;
		background: #141414;

		.record-btn {
			width: 100%;
			height: 244rpx;
			background: linear-gradient(180deg, #FFFFFF 0%, #D5D5D5 100%);
			position: absolute;
			bottom: 0;
			font-weight: 600;
			font-size: 28rpx;
			color: #464646;
			font-style: normal;
			z-index: 25;
		}

		.ly-close {
			width: 144rpx;
			height: 144rpx;
			position: absolute;
			left: 60rpx;
			bottom: 266rpx;
			z-index: 25;
			background: #333333;
			border-radius: 50%;

			text {
				color: #8F8F8F;
				font-size: 38rpx;
			}
		}
		
		.select {
			background: #FA5251;
		}

		.tape-box {
			width: 388rpx;
			height: 198rpx;
			position: absolute;
			background: #07C160;
			z-index: 25;
			left: 182rpx;
			bottom: 680rpx;
			border-radius: 16rpx;

			.tape-tips {
				width: 100%;
				height: 40rpx;
				font-weight: 600;
				font-size: 28rpx;
				color: #FFFFFF;
				line-height: 40rpx;
				font-style: normal;
				text-align: center;
				line-height: 40rpx;
			}

			.u-press {
				width: 100rpx;
				height: 100rpx;
			}

			.tape-title {
				width: 224rpx;
				height: 80rpx;
				font-weight: 600;
				font-size: 28rpx;
				color: #FFFFFF;
				line-height: 40rpx;
				text-align: center;
				font-style: normal;
			}

			.prompt-loader {
				width: 48rpx;
				height: 38rpx;
				display: flex;
				align-items: center;
				justify-content: space-between;
			}

			.prompt-loader .em {
				display: block;
				background: #fff;
				width: 1px;
				height: 40%;
				margin-right: 2.5px;
				float: left;
			}

			@keyframes load {
				0% {
					height: 40%;
				}

				50% {
					height: 100%;
				}

				100% {
					height: 40%;
				}
			}


			.prompt-loader .em:last-child {
				margin-right: 0px;
			}

			.prompt-loader .em:nth-child(1) {
				animation: load 2.5s 1.6s infinite linear;
			}

			.prompt-loader .em:nth-child(2) {
				animation: load 2.5s 1.8s infinite linear;
			}

			.prompt-loader .em:nth-child(3) {
				animation: load 2.5s 1s infinite linear;
			}

			.prompt-loader .em:nth-child(4) {
				animation: load 2.5s 1.8s infinite linear;
			}

			.prompt-loader .em:nth-child(5) {
				animation: load 2.5s 1.6s infinite linear;
			}

			.succ-title {
				width: 196rpx;
				height: 40rpx;
				font-weight: 600;
				font-size: 28rpx;
				color: #FFFFFF;
				line-height: 40rpx;
				text-align: center;
				font-style: normal;
			}

			.error-title {
				width: 344rpx;
				height: 80rpx;
				font-weight: 600;
				font-size: 28rpx;
				color: #FFFFFF;
				line-height: 40rpx;
				text-align: center;
				font-style: normal;
			}

		}


		.cancel {
			width: 100%;
			height: 40rpx;
			font-weight: 600;
			font-size: 28rpx;
			color: #B2B2B2;
			line-height: 40rpx;
			text-align: left;
			font-style: normal;
			position: absolute;
			bottom: 442rpx;
			padding: 0 70rpx;
			box-sizing: border-box;
			z-index: 24;
		}

		.tape-error {
			background-image: #FA5251;
		}
	}

	.flex-center {
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.column {
		flex-direction: column;
	}
	
	
</style>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值