@event {Function} stopRecord 主动停止录音
*/
props: {
recordOptions: {
type: Object,
default () {
return {
duration: 600000
}; // 请自行查看各端的的支持情况,这里全部使用默认配置
}
},
btnStyle: {
type: Object,
default () {
return {
width: '300rpx',
height: '80rpx',
borderRadius: '20rpx',
backgroundColor: '#fff',
border: '1rpx solid whitesmoke',
permisionState: false
};
}
},
btnHoverFontcolor: {
type: String,
default: '#000' // 颜色名称或16进制色值
},
btnDefaultText: {
type: String,
default: '长按开始录音'
},
btnRecordingText: {
type: String,
default: '录音中'
},
vibrate: {
type: Boolean,
default: true
},
// #ifdef APP-PLUS || MP-WEIXIN
popupTitle: {
type: String,
default: '正在录制音频'
},
popupDefaultTips: {
type: String,
default: '左右滑动后松手完成录音'
},
// #endif
// #ifdef H5
popupTitle: {
type: String,
default: '点击录制音频'
},
popupDefaultTips: {
type: String,
default: '点击完成录音'
},
// #endif
popupCancelTips: {
type: String,
default: '松手取消录音'
},
popupMaxWidth: {
type: Number,
default: 600 // 单位为rpx
},
popupMaxHeight: {
type: Number,
default: 300 // 单位为rpx
},
popupFixBottom: {
type: Number,
default: 200 // 单位为rpx
},
popupBgColor: {
type: String,
default: 'whitesmoke'
},
lineHeight: {
type: Number,
default: 50 // 单位为rpx
},
lineStartColor: {
type: String,
default: 'royalblue' // 颜色名称或16进制色值
},
lineEndColor: {
type: String,
default: 'indianred' // 颜色名称或16进制色值
}
},
data() {
return {
btnHoverBgcolor:'#0076fb',
stopStatus: true, // 是否已被父页面通知主动结束录音
btnTextContent: '按住说话',
startTouchData: {},
popupHeight: '0px', // 这是初始的高度
recording: false, // 修改初始值为 false
recordPopupShow: false,
recordTimeout: null, // 录音定时器
h5start: false
};
},
created() {
that = this;
// 请求权限
this.checkPermission();
// #ifdef APP-PLUS || MP-WEIXIN
recorderManager.onStop((res) => {
// 判断是否用户主动结束录音
if (that.recordTimeout !== null) {
// 延时未结束,则是主动结束录音
clearTimeout(that.recordTimeout);
that.recordTimeout = null; // 恢复状态
}
// 继续判断是否为取消录音
if (that.recording) {
that.$emit('endRecord', res);
} else {
this.btnHoverBgcolor = '#0076fb'; // 每次开始录音时重置为蓝色
// 用户向上滑动,此时松手后响应的是取消录音的回调
that.recording = true; // 恢复状态
that.$emit('cancelRecord');
}
that.recording = false; // 无论是正常结束还是取消,都设置为 false
});
recorderManager.onStart((err) => {
console.log('开始:', err);
});
recorderManager.onError((err) => {
console.log('err:', err);
});
// #endif
},
computed: {},
methods: {
upx2px(upx) {
return uni.upx2px(upx) + 'px';
},
async checkPermission() {
var that = this;
// #ifdef APP-PLUS
// 先判断os
let os = uni.getSystemInfoSync().osName;
if (os == 'ios') {
this.permisionState = await permision.judgeIosPermission('record');
} else {
this.permisionState = await permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
}
if (this.permisionState !== true && this.permisionState !== 1) {
uni.showToast({
title: '请先授权使用录音',
icon: 'none'
});
return;
}
// #endif
// #ifdef H5
if (!window.navigator?.mediaDevices?.getUserMedia) {
this.permisionState = false;
uni.showToast({
title: '请先授权使用录音',
icon: 'none'
});
return;
} else {
this.permisionState = true;
}
// #endif
// #ifdef MP-WEIXIN
uni.authorize({
scope: 'scope.record',
success(e) {
that.permisionState = true;
// that.startRecord();
},
fail() {
uni.showToast({
title: '请授权使用录音',
icon: 'none'
});
}
});
// #endif
},
startRecord() {
if (!this.permisionState) {
this.checkPermission();
return;
}
// #ifdef H5
if (this.h5start) {
this.h5start = false;
this.endRecord();
return;
}
this.h5start = true;
// #endif
this.stopStatus = false;
this.recording = true; // 开始录音时设置为 true
this.btnHoverBgcolor = '#0076fb'; // 每次开始录音时重置为蓝色
setTimeout(() => {
this.popupHeight = this.upx2px(this.popupMaxHeight);
setTimeout(() => {
this.recordPopupShow = true;
if (this.vibrate) {
// #ifdef APP-PLUS
// 震动
plus.device.vibrate(35);
// #endif
// #ifdef MP-WEIXIN
uni.vibrateShort();
// #endif
}
// 开始录音
recorderManager.start(this.recordOptions);
// 设置定时器
this.recordTimeout = setTimeout(
() => {
// 如果定时器先结束,则说明此时录音时间超限
this.stopRecord(); // 结束录音动画(实际上录音的end回调已经先执行)
this.recordTimeout = null; // 重置
},
this.recordOptions.duration ? this.recordOptions.duration : 600000
);
this.$emit('startRecord');
}, 100);
}, 200);
},
endRecord() {
var that = this;
if (this.stopStatus) {
return;
}
this.popupHeight = '0px';
this.recordPopupShow = false;
// #ifdef APP-PLUS || MP-WEIXIN
recorderManager.stop();
setTimeout(() => {
this.recording = false;
}, 100);
// #endif
// #ifdef H5
const res = recorderManager.stop();
if (that.recordTimeout !== null) {
// 延时未结束,则是主动结束录音
clearTimeout(that.recordTimeout);
that.recordTimeout = null; // 恢复状态
}
// 继续判断是否为取消录音
if (that.recording) {
that.$emit('endRecord', res);
} else {
this.btnHoverBgcolor = '#0076fb'; // 每次开始录音时重置为蓝色
// 用户向上滑动,此时松手后响应的是取消录音的回调
that.recording = true; // 恢复状态
that.$emit('cancelRecord');
}
// #endif
},
stopRecord() {
// 用法如你录音限制了时间,那么将在结束时强制停止组件的显示
this.endRecord();
this.stopStatus = true;
},
touchStart(e) {
this.startTouchData.clientX = e.changedTouches[0].clientX; //手指按下时的X坐标
this.startTouchData.clientY = e.changedTouches[0].clientY; //手指按下时的Y坐标
},
touchMove(e) {
let touchData = e.touches[0]; //滑动过程中,手指滑动的坐标信息 返回的是Objcet对象
let moveX = touchData.clientX - this.startTouchData.clientX;
let moveY = touchData.clientY - this.startTouchData.clientY;
if (moveY < -50) {
if (this.vibrate && this.recording) {
// #ifdef APP-PLUS
plus.device.vibrate(35);
// #endif
// #ifdef MP-WEIXIN
uni.vibrateShort();
// #endif
}
this.recording = false;
this.btnHoverBgcolor = '#ff0000'; // 向上滑动时变红
} else {
this.recording = true;
this.btnHoverBgcolor = '#0076fb'; // 恢复蓝色
}
}
}
};
</script>
<style lang="scss">
.record-btn {
color: #000;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
transition: 0.25s all;
border: 1rpx solid whitesmoke;
}
5 个回复
Diligent_UI - 【插件开发】【专治疑难杂症】【多款插件已上架:https://ext.dcloud.net.cn/publisher?id=193663(微信搜索飘逸科技UI小程序直接体验)】【骗子请绕道】问题咨询请加QQ群:120594820,代表作灵感实用工具小程序
从文档来看,这些鼠标事件好像都没有写,用css伪类试试实现需求
叫啥好呢
解决了吗?
d***@163.com
服了这玩意了
DCloud_UNI_JBB
我长按松开手指之后并没有出现不触发 touchEnd 事件的情况,可以提供更多复现信息吗
7***@qq.com
<template>
v-if="recordPopupShow" class="record-popup"<view>
<!-- #ifdef APP-PLUS ||MP-WEIXIN -->
style="{ color: recording ? '#1E1F23' : 'red' }"
</view>
</template>
<script>
var that;
// #ifdef APP-PLUS || MP-WEIXIN
const recorderManager = uni.getRecorderManager();
// #endif
// #ifdef H5
import speech from '../../js_sdk/h5-speech/speech.js';
const recorderManager = new speech(8000);
// #endif
// #ifdef APP-PLUS
// 引入权限判断
import permision from '../../js_sdk/wa-permission/permission.js';
// #endif
export default {
name: 'nbVoiceRecord',
/**
@event {Function} stopRecord 主动停止录音
*/
props: {
recordOptions: {
type: Object,
default () {
return {
duration: 600000
}; // 请自行查看各端的的支持情况,这里全部使用默认配置
}
},
btnStyle: {
type: Object,
default () {
return {
width: '300rpx',
height: '80rpx',
borderRadius: '20rpx',
backgroundColor: '#fff',
border: '1rpx solid whitesmoke',
permisionState: false
};
}
},
btnHoverFontcolor: {
type: String,
default: '#000' // 颜色名称或16进制色值
},
btnDefaultText: {
type: String,
default: '长按开始录音'
},
btnRecordingText: {
type: String,
default: '录音中'
},
vibrate: {
type: Boolean,
default: true
},
// #ifdef APP-PLUS || MP-WEIXIN
popupTitle: {
type: String,
default: '正在录制音频'
},
popupDefaultTips: {
type: String,
default: '左右滑动后松手完成录音'
},
// #endif
// #ifdef H5
popupTitle: {
type: String,
default: '点击录制音频'
},
popupDefaultTips: {
type: String,
default: '点击完成录音'
},
// #endif
popupCancelTips: {
type: String,
default: '松手取消录音'
},
popupMaxWidth: {
type: Number,
default: 600 // 单位为rpx
},
popupMaxHeight: {
type: Number,
default: 300 // 单位为rpx
},
popupFixBottom: {
type: Number,
default: 200 // 单位为rpx
},
popupBgColor: {
type: String,
default: 'whitesmoke'
},
lineHeight: {
type: Number,
default: 50 // 单位为rpx
},
lineStartColor: {
type: String,
default: 'royalblue' // 颜色名称或16进制色值
},
lineEndColor: {
type: String,
default: 'indianred' // 颜色名称或16进制色值
}
},
data() {
return {
btnHoverBgcolor:'#0076fb',
stopStatus: true, // 是否已被父页面通知主动结束录音
btnTextContent: '按住说话',
startTouchData: {},
popupHeight: '0px', // 这是初始的高度
recording: false, // 修改初始值为 false
recordPopupShow: false,
recordTimeout: null, // 录音定时器
h5start: false
};
},
created() {
that = this;
},
computed: {},
methods: {
upx2px(upx) {
return uni.upx2px(upx) + 'px';
},
async checkPermission() {
var that = this;
// #ifdef APP-PLUS
// 先判断os
let os = uni.getSystemInfoSync().osName;
if (os == 'ios') {
this.permisionState = await permision.judgeIosPermission('record');
} else {
this.permisionState = await permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
}
if (this.permisionState !== true && this.permisionState !== 1) {
uni.showToast({
title: '请先授权使用录音',
icon: 'none'
});
return;
}
// #endif
// #ifdef H5
if (!window.navigator?.mediaDevices?.getUserMedia) {
this.permisionState = false;
uni.showToast({
title: '请先授权使用录音',
icon: 'none'
});
return;
} else {
this.permisionState = true;
}
// #endif
this.recording = false;
}, 100);
// #endif
// #ifdef H5
const res = recorderManager.stop();
if (that.recordTimeout !== null) {
// 延时未结束,则是主动结束录音
clearTimeout(that.recordTimeout);
that.recordTimeout = null; // 恢复状态
}
}
};
</script>
<style lang="scss">
.record-btn {
color: #000;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
transition: 0.25s all;
border: 1rpx solid whitesmoke;
}
.record-btn-hover {
color: var(--btn-hover-fontcolor) !important;
background-color: var(--btn-hover-bgcolor) !important;
}
.record-popup {
position: absolute;
width: 100%;
color: rgb(30, 31, 35);
top: -60rpx;
text-align: center;
}
.cancel-icon {
width: 100rpx;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 44rpx;
line-height: 44rpx;
background-color: pink;
border-radius: 50%;
transform: rotate(45deg);
}
.voice-line-wrap {
display: flex;
align-items: center;
position: absolute;
left: 0;
top: 0;
justify-content: center;
width: 100%;
height: 100%;
.voice-line {
width: 5rpx;
height: var(--line-height);
border-radius: 3rpx;
margin: 0 5rpx;
}
}
@keyframes wave {
0% {
transform: scale(1, 1);
background-color: var(--line-start-color);
}
}
</style>