目录
效果描述
在与好友的对话框中,点击语音图标可以切换到给好友发送语音,长按发送语音的按钮即可开始录音:
如果录制时间 小于60s时,松手则表示录音结束并将语音消息发送给对方;
如果录制的时间 超过60s则自动结束,并将语音发送给对方;
如果在录制 60s之内并且没有松手,而是上滑100像素,则表示取消发送该条语音;
效果展示
默认页面 语音消息录制中 取消发送 发送成功
代码实现
发送语音部分的代码是全的,但是别的部分代码有缺失,如果需要对话框页面完整代码的可以私信。
渲染层
html
<view class="guding">
<view class="bottom" :style="bottomStyle">
<view class="mic">
<uv-icon name="mic" color="#09B5BE" size="50rpx" v-if="!isVoice" @click="handleVoice(true)"></uv-icon>
<image src="../../static/message/keyboard.svg" mode="aspectFill" class="img" v-if="isVoice"
@click="handleVoice(false)"></image>
</view>
<view class="b-cen" v-if="!isVoice">
<!-- autoHeight:是否自动增加高度,设置auto-height时,height不生效 -->
<uv-textarea ref="textarea" v-model="msgText" autoHeight border="none" @input="input" :adjustPosition="true"
@focus="focus" @blur="blur" :showConfirmBar="false" maxlength="100"
:customStyle="{minHeight:'30rpx',borderRadius:'20rpx'}" :textStyle="{fontSize:'30rpx'}"></uv-textarea>
<image v-if="isShowSmile" src="../../static/message/smile.svg" mode="aspectFill" class="img"
@click="handleKeySmile('smile')"></image>
<image v-if="isShowKeyboard" src="../../static/message/keyboard.svg" mode="aspectFill" class="img"
@click="handleKeySmile('key')"></image>
</view>
<view v-if="isVoice" class="b-cen">
<view class="bc-text" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove">按住 说话</view>
</view>
<view v-if="!msgText.length" class="mic" @click="handlePlus"><uv-icon name="plus" color="#09B5BE"
size="50rpx"></uv-icon></view>
<view class="sendBtn" v-if="msgText.length" @click="handleSubmit">发送</view>
</view>
<view class="emoji" v-if="!isShowSmile">
<text class="e-item" v-for="(item,index) in emojiList" :key="index" @click="handleEmoji(item)">{{item}}</text>
</view>
<view class="extra" v-if="isShowExtra">
<view v-for="item in extraList" :key="item.id" class="ex-item" @click="handleExtra(item)">
<uv-icon :name="item.icon" size="74rpx"></uv-icon>
<text>{{item.text}}</text>
</view>
</view>
</view>
逻辑层
javascript
const recorderManager = ref('');
const isVoice = ref(false) //是否显示语音
const isshowVoiceBg = ref(false) //是否显示录音背景
// 切换语音和键盘
const handleVoice = (val) => {
isVoice.value = val
isShowExtra.value = false
inputh.value = 0
isShowSmile.value = true
isShowKeyboard.value = false
if (val) {
uni.authorize({
scope: 'scope.record',
desc: '需要获取您的录音权限',
fail(res) {
uni.showToast({
title: "请点击右上角"..."功能菜单,进入设置界面,打开麦克风权限后,再重新录音",
icon: "none",
duration: 2000,
});
return false;
},
})
}
}
const pageY = ref(0)
const timer = ref(0) //计时器
const vlength = ref(0) //录音时长
// 点击开始录制语音
const touchstart = (e) => {
console.log("开始录制", e)
let i = 1;
timer.value = setInterval(() => {
vlength.value = i;
i++;
console.log("计时器开始工作,第几秒", i)
//结束计时,如果录制时间超过60s就强制停止录音
if (i > 60) {
clearInterval(timer.value);
touchend();
}
}, 1000)
recorderManager.value.start();
pageY.value = e.changedTouches[0].pageY;
isshowVoiceBg.value = true
}
const isCancel = ref(false)
const recordSend = ref(true)
// 结束录音
const touchend = async (e) => {
console.log("结束录制", e)
recorderManager.value.stop();
clearInterval(timer.value)
isshowVoiceBg.value = false
// 如果取消发送录音,则不发送
if (isCancel.value) {
recordSend.value = false
} else {
recordSend.value = true
}
// 结束录音后重置取消状态
isCancel.value = false
}
// 删除录音
const touchmove = (e) => {
console.log('删除录音')
// 如果手指移动距离大于100,则关闭录音界面
if (pageY.value - e.changedTouches[0].pageY > 100) {
// 关闭录音界面
isshowVoiceBg.value = false
isCancel.value = true
}
}
onMounted(() => {
recorderManager.value = uni.getRecorderManager()
// 处理录音停止的逻辑
recorderManager.value.onStop(async (res) => {
console.log("录制结束后生成的声音文件", res, vlength.value)
await http.uploadFile(api.singleUpload, res.tempFilePath).then(res => {
console.log("录制的时长为多少", vlength.value)
let data = {
voice: res.data.filePath,
time: vlength.value
};
if (recordSend.value) {
sendMsg({ type: 2, message: JSON.stringify(data) }) //语音
} else {
uni.showToast({
icon: "none",
title: "语音已取消发送"
})
}
})
// 重置时长和状态
vlength.value = 0;
isshowVoiceBg.value = false
});
})