小程序提供了<camera>标签和createCameraContext API ,允许开发者进行图片拍摄和视频录制,这个功能还是蛮强大的。
我们主要使用了视频录制的这个功能,将其中遇到的问题和需要注意的点来说明一下:
(我是用taro开发的,所以接下来的一些代码片段也是taro的格式,不过taro的API调用方法和微信原生几乎是一样的,标签也只是更改了标签的写法,短连接线的形式改成驼峰的书写形式)
先把问题总结一下,然后在下面放一些代码的片段出来(如果大家看到上面就已经把问题解决了,那就不用看下面长长的代码段啦):
1.Camera上面要是想自定义元素的话,只能使用coverView和CoverImage标签,虽然我们测试发现使用View也是OK的,但是还是会有CoverView的一些限制,所以我就索性直接使用官方文档上面的写法。
2.CoverView如果设置了宽度之后,显示文字可能会导致ios上面文字显示不全,这个我们用了一个投机的方法,加上了一个 解决的,这个问题在小程序社区里面看到有人使用map的方式也能解决,但是那样的话觉得很奇怪,而且在稍微慢点的手机上能看到文字是一个字一个字出来的,所以就放弃哪种办法,选择这种解决方案。
3.下面就说说startRecord的 timeoutCallback,这个问题可能会有一些人漏掉(反正我是漏掉了),这是一点,还有一点就是当触发了timeoutCallback后,不同系统的手机上面表现不一一下那个需要大家注意一下,在安卓手机上,执行完timeoutCallback之后在执行stopRecord 会报错“operateCamera:fail:is not recording”,而在ios手机上,执行timeoutCallback之后,stopRecord不会执行,所以大家在编码的时候要考虑处理一下这个情况。
下面是整个流程相对关键的代码片段:
1.首先要创建camera上下文cameraContext对象。(我是在constructor里面创建的),你要保证页面页面上只有一个<camera>标签,然后这个cameraContext对象会与之关联
this.cameraCtx = Taro.createCameraContext();
2.接下来我们写写的<camera>标签的内容,我们的需求是要在camera上面自定义一些元素,所以相对复杂了点,大概就是这个样子的了。
<Camera className='camera' devicePosition={position}> <CoverView className='cameraCover'> <CoverView className='cameraTitle'> <CoverView className='cameraHeader'> <CoverView className='leftHeader'> <CoverImage src={closeIcon} className='cameraHeaderIcon cameraCloseIcon' onClick={onCancel} /> <CoverImage src={toggleIcon} className='cameraHeaderIcon' onClick={this.togglePos} /> </CoverView> {showSquare && <CoverView className='squareBox'> <CoverImage src={squareIcon} className='cameraHeaderIcon squareIcon' onClick={this.gotoSquare} /> <CoverView className='squareText'> <CoverView>没思路?去看看别人怎么拍的 </CoverView> </CoverView> </CoverView>} </CoverView> </CoverView> </CoverView></Camera>
3.下面就是重头戏了,控制视频的录制与结束录制。我们的需求要求录制的时候显示录制的时长,给一个最大的时间值,视频可以自己结束录制,也可以手动的停止录制。
接下来说明一下代码:
1)开始录制和结束录制之前的那个startDelay, stopDelay是用来防止按钮频繁点击操作的,因为不管是开始录制还是结束录制都是一个相对耗时的操作,频繁点击可能会出现其他问题
2)然后就是参照文档编写开始录制和结束录制的代码了,这里着重说明一下startRecord 里面的timeoutCallback,小程序文档上说明小程序最长只能录制30s的视频,就有这么一个超时回调函数,视频一旦超时之后就会触发,但是超时的视频再执行stopRecord在不同系统的手机上表现是不一样的,在安卓手机上会报错"operateCamera:fail:is not recording",在ios手机上直接就不执行stopRecord了,所以我这块做的处理是如果超时了,就在这里面执行一些 stopRecord success的方法,如果手动执行停止录制,执行下面定义的stopRecord(注意,不是Taro.stopRecord哦)
startRecord = () => { const { startDelay } = this.state; if (startDelay) { return; } this.setState({ startDelay: true }, () => { this.cameraCtx.startRecord({ success: () => { this.setState({ cameraState: RECORDING, recordText: TEXT_RECORDING }, () => { this.recordTimer = setInterval(() => { this.setState({ timer: this.state.timer + 1 }); }, 1000); }); }, fail: (err) => { console.log('开始录制失败', err); }, complete: () => { this.setState({ startDelay: false }); }, timeoutCallback: (res) => { // TODO: 都是30,先不做判断了 this.setState({ cameraState: COMPLETE, currentMedia: { img: res.tempThumbPath, video: res.tempVideoPath, duration: 30 }, stopDelay: false }); } }) }); } stopRecord = () => { const { stopDelay } = this.state; if (stopDelay) { return; } this.setState({ stopDelay: true }, () => { const { timer } = this.state; if (timer < MIN_DURATION) { showToast('录制时长不得小于' + MIN_DURATION + '秒'); return; } clearInterval(this.recordTimer); this.cameraCtx.stopRecord({ success: (res) => { this.setState({ cameraState: COMPLETE, currentMedia: { img: res.tempThumbPath, video: res.tempVideoPath, duration: timer } }) }, fail: (err) => { console.log('结束录制失败', err); }, complete: () => { this.setState({ stopDelay: false }); } }) }); }
整个流程大概就是这样啦~~