uniapp小程序实现长按录音、上滑取消的与语言录入模块(CSS实现语音音阶动画效果)

语言录入模块 实现效果

在这里插入图片描述


HTML部分

代码如下:

<template>
	<view :class="longPress == '1' ? 'record-layer' : 'record-layer1'">
		<view  :class="longPress == '1' ? 'record-box' : 'record-box1'">
			<view class="record-btn-layer">
				<button class="record-btn" :class="longPress == '1' ? 'record-btn-1' : 'record-btn-2'" :style="VoiceTitle != '松开手指,取消发送' && longPress != '1'?'background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);':'background-color: rgba(0, 0, 0, .5);color:white'"
					@longtap="longpressBtn" @touchend="touchendBtn()" @touchmove="handleTouchMove" @touchstart="longpressBtn">
					<image
						src="https://penghuahai.obs.cn-south-1.myhuaweicloud.com:443/penghuahai%2Fblind%2F1659237233452.png" />
					<text>{{VoiceText}}</text>
				</button>
			</view>
			<!-- 语音音阶动画 -->
			<view :class="VoiceTitle != '松开手指,取消发送'?'prompt-layer prompt-layer-1':'prompt-layer1 prompt-layer-1'"  v-if="longPress == '2'">
				<view class="prompt-loader">
					<view class="em" v-for="(item,index) in 15" :key="index"></view>
				</view>
				<text class="span">{{VoiceTitle}}</text>
			</view>
		</view>
	</view>
</template>

JS部分

代码如下:

<script>
	import {
		get,
		post,
		uploadFile
	} from "../../utils/request.js"
	const recorderManager = uni.getRecorderManager()
	var init // 录制时长计时器
	var timer // 播放 录制倒计时
	export default {
		data() {
			return {
				longPress: '1', // 1显示 按住 说话 2显示 说话中
				delShow: false, // 删除提示框显示隐藏
				time: 0, //录音时长
				duration: 60000, //录音最大值ms 60000/1分钟
				tempFilePath: '', //音频路径
				startPoint: {}, //记录长按录音开始点信息,用于后面计算滑动距离。
				sendLock: true, //发送锁,当为true时上锁,false时解锁发送
				VoiceTitle:'松手结束录音',
				recorderManager: uni.getRecorderManager(), 
				VoiceText:'按住 说话',
				types:''
			}
		},
		props:['type'],
		created:function(){
				this.types=this.type;
				console.log(this.type)//打印父组件传过来的参数
		},
		methods: {
			// 长按录音事件
			longpressBtn(e) {
				this.startPoint = e.touches[0];//记录长按时开始点信息,后面用于计算上划取消时手指滑动的距离。
				this.longPress = '2';
				this.VoiceText='说话中...';
				recorderManager.onStop((res) => {
					// console.log(res);
					this.tempFilePath = res.tempFilePath;
				})
				const options = {
					duration: this.duration, // 指定录音的时长,单位 ms
					sampleRate: 16000, // 采样率
					numberOfChannels: 1, // 录音通道数
					encodeBitRate: 96000, // 编码码率
					format: 'mp3', // 音频格式,有效值 aac/mp3
					frameSize: 10, // 指定帧大小,单位 KB
				}
				this.recorderManager.start(options);
				// 监听音频开始事件
				this.sendLock = false;//长按时是不上锁的。
				recorderManager.onStart((res) => {})
			},
			// 长按松开录音事件
			touchendBtn() {
				this.longPress = '1';
				this.VoiceText='按住 说话';
				this.VoiceTitle = '松手结束录音'
				recorderManager.onStop((res) => {
					console.log(this.sendLock);
					if (this.sendLock) {
					  //上锁不发送
					} else {//解锁发送,发送网络请求
					  if (res.duration < 1000)
					        wx.showToast({
					              title: "录音时间太短",
					              icon: "none",
					              duration: 1000
					        });
					   else {
						   this.tempFilePath = res.tempFilePath
						   uploadFile({
						   	url: '/voice/VoiceControl',
						   	src: res.tempFilePath,
						   }).then(res => {
						   	console.log(JSON.parse(res.data));
						   })
					   }
					}
				})
				
				// this.recordingTimer(this.time)
				this.recorderManager.stop();//结束录音
			},
			// 删除录音
			      handleTouchMove(e) {
			          //touchmove时触发
			          var moveLenght = e.touches[e.touches.length - 1].clientY - this.startPoint.clientY; //移动距离
			          if (Math.abs(moveLenght) > 70) {
			            // wx.showToast({
			            //       title: "松开手指,取消发送",
			            //       icon: "none",
			            //       duration: 60000
			            // });
						// console.log("松开手指,取消发送");
						this.VoiceTitle = "松开手指,取消发送";
						this.VoiceText='松开手指,取消发送';
						this.delBtn()
			            this.sendLock = true;//触发了上滑取消发送,上锁
			          } else {
			            // wx.showToast({
			            //       title: "正在录音,上划取消发送",
			            //       icon: "none",
			            //       duration: 60000
			            // });
						this.VoiceTitle = "松手结束录音";
						this.VoiceText='松手结束录音';
			            this.sendLock = false;//上划距离不足,依然可以发送,不上锁
			          }
			    },
			delBtn() {
				this.delShow = false;
				this.time = 0
				this.tempFilePath = '';
				// this.VoiceTitle = '松手结束录音'
			},
		}
	}
</script>

CSS部分

代码如下:

<style lang="less">
	/* 语音录制开始--------------------------------------------------------------------- */
	.record-layer {
		width: 91vw;
		// padding: 300px 0;
		box-sizing: border-box;
		height: 15vw;
		position: fixed;
		margin-left: 4vw;
		z-index: 10;
		bottom: 3vh;
	}
	
	.record-layer1 {
		width: 100vw;
		// padding: 300px 0;
		box-sizing: border-box;
		height: 100vh;
		position: fixed;
		background-color: rgba(0, 0, 0, .6);
		// padding: 0 4vw;
		z-index: 10;
		bottom: 0vh;
	}

	.record-box {
		width: 100%;
		position: relative;
	}
	.record-box1 {
		width: 100%;
		position: relative;
		    bottom: -83vh;
		    height: 17vh;
	}
	.record-btn-layer {
		width: 100%;
	}

	.record-btn-layer button::after {
		border: none;
		transition: all 0.1s;
	}

	.record-btn-layer button {
		font-size: 14px;
		line-height: 50px;
		width: 100%;
		height: 50px;
		border-radius: 8px;
		text-align: center;
		background: #FFD300;
		transition: all 0.1s;
	}

	.record-btn-layer button image {
		width: 16px;
		height: 16px;
		margin-right: 4px;
		vertical-align: middle;
		transition: all 0.3s;
	}
.record-btn-layer .record-btn-1 {
		background-image: linear-gradient(to right, #43e97b 0%, #38f9d7 100%);
		color: #000000!important;
		
	}

	.record-btn-layer .record-btn-2 {
		border-radius: 168rpx 168rpx 0 0;
		height: 17vh;
		line-height: 17vh;
		transition: all 0.3s;
	}

	/* 提示小弹窗 */
	.prompt-layer {
		border-radius: 15px;
		background: #95EB6C;
		padding: 8px 16px;
		box-sizing: border-box;
		position: absolute;
		left: 50%;
		height: 11vh;
		transform: translateX(-50%);
		transition: all 0.3s;
	}

	.prompt-layer::after {
		content: '';
		display: block;
		border: 12px solid rgba(0, 0, 0, 0);
		border-radius: 10rpx;
		border-top-color: #95EB6C;
		position: absolute;
		bottom: -46rpx;
		left: 50%;
		transform: translateX(-50%);
		transition: all 0.3s;
	}
    //取消动画
	.prompt-layer1 {
		border-radius: 15px;
		background: #FB5353;
		padding: 8px 16px;
		box-sizing: border-box;
		position: absolute;
		left: 50%;
		height: 11vh;
		transform: translateX(-50%);
		transition: all 0.3s;
	}
	
	.prompt-layer1::after {
		content: '';
		display: block;
		border: 12px solid rgba(0, 0, 0, 0);
		border-radius: 10rpx;
		border-top-color: #FB5353;
		position: absolute;
		bottom: -46rpx;
		left: 50%;
		transform: translateX(-50%);
		transition: all 0.3s;
	}
	.prompt-layer-1 {
		font-size: 12px;
		width: 150px;
		text-align: center;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		top: -400rpx;
	}

	.prompt-layer-1 .p {
		color: #000000;
	}

	.prompt-layer-1 .span {
		color: rgba(0, 0, 0, .6);
	}

	.prompt-loader .em {}

	/* 语音音阶------------- */
	.prompt-loader {
		width: 96px;
		height: 20px;
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-bottom: 6px;
	}

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

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

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

	.prompt-loader .em:nth-child(2) {
		animation: load 2.5s 1.2s 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 0.8s infinite linear;
	}

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

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

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

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

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

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

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

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

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

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

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

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

		50% {
			height: 100%;
		}

		100% {
			height: 10%;
		}
	}

	/* 语音音阶-------------------- */
	.prompt-layer-2 {
		top: -40px;
	}

	.prompt-layer-2 .text {
		color: rgba(0, 0, 0, 1);
		font-size: 12px;
	}

	/* 语音录制结束---------------------------------------------------------------- */
</style>


总结

以上就是语言录入模块的实现共享
借鉴学习于:https://blog.csdn.net/tianpeng1996/article/details/119652550

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在 uView-UI 中,uni-app 小程序中的表单输入框是不支持直接进行语音录入的。不过,你可以通过一些额外的操作来实现语音录入的功能。以下是一种可能的实现方式: 1. 在输入框旁边添加一个按钮或图标,用来触发语音录入功能。 2. 绑定按钮的点击事件,当用户点击按钮时,调用微信小程序语音录入接口或其他语音识别相关的 API。 3. 在语音录入接口的回调函数中,将语音转换为文本,并将文本填充到输入框中。 具体实现步骤如下: 1. 在你的表单输入框组件中,添加一个按钮或图标,用来触发语音录入功能,代码类似下面这样: ```vue <template> <view> <input v-model="inputValue" placeholder="请输入文本" /> <button @click="startVoiceInput">语音输入</button> </view> </template> <script> export default { data() { return { inputValue: '' }; }, methods: { startVoiceInput() { // 调用微信小程序语音录入接口或其他语音识别相关的 API // 在回调函数中将语音转换为文本,并填充到输入框中 } } }; </script> ``` 2. 在 `startVoiceInput` 方法中,调用微信小程序语音录入接口或其他语音识别相关的 API。具体的调用方式和参数配置可以参考相关文档或 API 文档。 3. 在语音录入接口的回调函数中,将语音转换为文本,并将文本填充到输入框中。具体的语音转文本操作可能会因使用的语音识别服务而有所不同。你可以根据所选的语音识别服务的文档,了解如何将语音转换为文本,并将其填充到表单输入框中。 请注意,以上步骤仅为一种实现语音录入功能的示例,具体的实现方式可能会根据你使用的语音识别服务和相关 API 的不同而有所差异。你需要根据自己的项目需求和使用的语音识别服务进行相应的操作和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值