php按住说话然后播放,小程序仿微信聊天按住说话功能

这篇博客详细介绍了如何在微信小程序中实现仿微信聊天的录音功能,包括按住说话、上滑取消发送、录音时间限制以及录音动画的实现。通过监听触摸事件并结合动画效果,提供用户友好的交互体验。同时,为了解决快速点击导致的录音问题,采用了延迟处理策略,并通过随机更换图片模拟录音动画,以弥补无法获取实时音量数据的不足。
摘要由CSDN通过智能技术生成

小程序仿微信聊天按住说话功能

实现:按住说话有录音动画,上滑可取消发送,松开发送录音

录音授权判断

# .wxml

bind:longpress="onLongpress" catch:touchmove="onTouchMove">{{touchBtn?'松开 结束':'按住说话'}}

复制代码

// # ontouchstart

record() {

const scopeRecord = app.globalData.scopeRecord;

// 无授权时获取授权

if (!scopeRecord) {

getScopeRecord();

return;

}

this.data.touched = true;

// 触发父组件录音事件,由父组件调用录音API

this.triggerEvent('startRecord')

},

复制代码

上滑取消发送,利用滑动距离判断是否取消,

onTouchMove(e) {

if (e.touches[0].clientY < 520) {

// # 取消发送

this.data.cancelRecord = true;

wx.showToast({

title: '松开,取消发送',

duration: 10000,

image: '/page/common/resource/image/cancel.png'

})

} else {

// # 不取消

this.showMicAni(1);

this.data.cancelRecord = false;

}

},

复制代码

松开发送 - 快速点击bug

bug:快速点击按钮,一直显示录音中 原因:调起录音API需要一定时间,会出现touchstart->touchend->调起录音API,touchend事件在录音前触发了,无法再调起停止录音API

思路:可以在调用录音后用个变量a标识,在!a时执行touchend后则用变量b标识,在调用录音后若有b则再立即停止录音。但该方法涉及太多变量传递(父传子,子传父),就偷了下懒用了个400ms的延时

onTouchEnd(e) {

if (!this.data.touched) return;

this.data.touched = false;

wx.hideToast();

// 延时处理 防止录音未调起就触发停止

setTimeout(() => {

this.triggerEvent('stopRecord', {

// # 判断是否取消发送

send: !this.data.cancelRecord

});

}, 400);

}

},

复制代码

除了说话中,上滑取消外,还要加多个说话时间太短的提示

方案一:我用了小程序的longpress事件做判断,未触发该事件则属于说话太短;同时,如果在没在触发Longpress前触发了上滑也默认开启录音

方案二:touchstart时开始计时,touchend结束计时,用时间来判断

// # 利用长按判断录音是否太短

onLongpress() {

this.data.recording = true;

},

// # 上滑时默认录音中

onTouchMove(e) {

this.data.recording = true;

if (e.touches[0].clientY < 520) { ... } else { ... }

},

onTouchEnd(e) {

if (this.data.recording) {

// # 触发停止...

} else {

wx.showToast({

title: '说话时间太短',

duration: 500,

image: '/page/common/resource/image/warn-b.png'

})

// # 触发停止...

}

},

复制代码

录音动画 — 实现微信聊天录音中可根据音量大小改麦克风音量提示的动画的toast。

问题:官方API中录音回调没提供音量数据,无法根据音量来做动画。而且我们使用了wx.showToast,image无法使用动图,也无法自定义动画

思路:既然无法获取音量数据,又需要用户感知有在录音中,还无法做动画。我想了个方法,能不能每隔一段时间换一张image直到录音停止,而且更换图片的顺序不能是固定的,这样看起来很假,必须随机更换图片

注意:touchend和touchmove要清空定时器,touchmove手指回到按钮则要再次调用showMicAni

showMicAni(i) {

// # 初始化间隔时间

let delay = 500;

let that = this;

wx.showToast({

title: '上滑,取消发送',

duration: 60000,

// # 准备5张麦克风不同状态的png

image: '/page/common/resource/image/mic0' + i + '.png'

})

that.data.time1 = setTimeout(() => {

// util.getRandomInt公共方法,随机生成【1,5】中的整数

i = util.getRandomInt(1, 5)

that.showMicAni(i)

}, delay);

},

// touchstart

record() {

// # 开始录音...

this.showMicAni(1);

},

onTouchEnd() {

clearTimeout(this.data.time1)

},

onTouchMove(e) {

clearTimeout(this.data.time1)

if (e.touches[0].clientY < 520) {

// # 取消发送...

} else {

this.showMicAni(1);

this.data.cancelRecord = false;

}

},

复制代码

以下是完整代码

// # .js

import wlogin from '../../../common/resource/js/login.js';

import util from '../../../../utils/util'

let app = getApp();

const getScopeRecord = wlogin.recordInpower();

Component({

properties: {},

data: {

touchBtn: false,

},

ready() {},

methods: {

// 利用长按判断录音是否太短

onLongpress() {

this.data.recording = true;

},

// touchstart

record() {

const scopeRecord = app.globalData.scopeRecord;

if (!scopeRecord) {

getScopeRecord();

return;

}

this.data.recording = false;

this.data.touched = true;

this.data.cancelRecord = false;

this.setData({

touchBtn: true

})

this.triggerEvent('startRecord')

this.showMicAni(1);

},

showMicAni(i) {

let delay = 500;

let that = this;

wx.showToast({

title: '上滑,取消发送',

duration: 60000,

image: '/page/common/resource/image/mic0' + i + '.png'

})

that.data.time1 = setTimeout(() => {

// 随机生成

i = util.getRandomInt(1, 5)

that.showMicAni(i)

}, delay);

},

onTouchMove(e) {

this.data.recording = true;

clearTimeout(this.data.time1)

if (e.touches[0].clientY < 520) {

this.data.cancelRecord = true;

wx.showToast({

title: '松开,取消发送',

duration: 10000,

image: '/page/common/resource/image/cancel.png'

})

} else {

this.showMicAni(1);

this.data.cancelRecord = false;

}

},

onTouchEnd(e) {

clearTimeout(this.data.time1)

if (this.data.recording) {

if (!this.data.touched) return;

this.data.touched = false;

wx.hideToast();

setTimeout(() => {

this.triggerEvent('stopRecord', {

send: !this.data.cancelRecord

});

}, 400);

} else {

wx.showToast({

title: '说话时间太短',

duration: 500,

image: '/page/common/resource/image/warn-b.png'

})

// 延时处理 防止录音未调起就触发停止

setTimeout(() => {

this.triggerEvent('stopRecord', {send: false});

}, 400);

}

this.setData({touchBtn: false})

},

})

复制代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值