小程序 坑

textarea 在安卓上删除字符时会执行2次input事件

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

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

  • 首先进行录音授权判断
# .wxml
<view class="btn {{touchBtn?'hoverBtn':''}}" catch:touchend="onTouchEnd" bind:touchstart="record"
bind:longpress="onLongpress" catch:touchmove="onTouchMove">{{touchBtn?'松开 结束':'按住说话'}}</view>
复制代码
// # 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:快速点击按钮,一直显示录音中 原因:调起录音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直到录音停止,而且更换图片的顺序不能是固定的,这样看起来很假,必须随机更换图片
  • 注意:touchendtouchmove要清空定时器,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})
    },
})
复制代码

原生组件层级过高

canvas

  1. 在组件内使用画布,第二个参数必须带
wx.createCanvasContext(id, this);
复制代码
  1. 画面层级最高不能控制,若须被覆盖,可以用

环形实时进度条

录音授权

wx.pageScrollTo bug

  1. 在部分安卓机型中,例如华为等机型会在滚动的时候,触发一下拉刷新,也就是说,在触发wx.pageScrollTo之后,会先滚动到最顶端,触发刷新,再从最顶端滚动到我们需要的位置。(这是十分影响用户体验的,整体效果非常差)
  2. 在iphone机型中,在触发wx.pageScrollTo时,如果页面中有fixed定位的元素,定位的元素会跟随页面滚动,再回到位置上
  3. 将pageScrollTo的滚动动画时间duration设置为0后,在真机上,都不会出现抖动的问题,因为这个过程其实是直接跳过了,但是直接出来整体的体验也十分糟糕.

转载于:https://juejin.im/post/5ba34d5a6fb9a05cd676b399

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值