关于小程序模仿微信语音发送功能的Wepy代码
<style lang="scss"> page { height: 100%; } .main { display: flex; flex-direction: column; height: 100%; } .output-audio { width: 160rpx; margin: 5rpx 30rpx; .audio { position: relative; top: 0; left: 0; height: 28rpx; padding: 20rpx; border-radius: 35rpx; background-color: #226fe3; border: 1px solid #f0f0f0; .ico { width: 26rpx; height: 28rpx; float: left; } .time { position: absolute; top: 18rpx; right: -50rpx; font-size: 24rpx; } } } .section { flex: 0 0 100rpx; width: 100%; height: 100rpx; padding: 15rpx; box-sizing: border-box; z-index: 1; background-color: #ffffff; .input-view { width: 100%; height: 70rpx; .input-icon { display: inline-block; .audio-icon { width: 70rpx; height: 70rpx; } } .audio-btn { display: inline-block; width: 700rpx; height: 70rpx; font-size: 32rpx; color: #747474; background-color: #f7f6f6; line-height: 70rpx; margin: 0 auto; } } } </style> <template> <view class="main"> <!-- 录音音频区 --> <block wx:for="{{audioArr}}" wx:key="content" wx:for-item="item" wx:for-index="index" data-state="{{item.state}}" > <view class="output-audio" style="width: {{item.time < 8 ? 64 : item.time * 8}}rpx;"> <view class="audio" wx:if="{{item.state==false}}" data-index="{{index}}" @tap="audioPlay"> <image class="ico" src="../images/play-icon.png" /> <label class="time">{{item.time}}"</label> </view> <view class="audio" wx:if="{{item.state==true}}" data-index="{{index}}" @tap="audioStop"> <image class="ico" src="../images/play-icon-gif.gif" /> <label class="time">{{item.time}}"</label> </view> </view> </block> <!-- 录音点击区域 --> <view class="section"> <view class="input-view"> <button class="audio-btn" @longpress="handleRecordStart" @touchend="handleRecordStop" @touchmove="handleTouchMove" >{{text}}</button> </view> </view> </view> </template> <script> import wepy from "wepy"; import qiniuUploader from "../common/qiniuUploader.js"; // 七牛Js export default class Index extends wepy.page { config = { navigationBarTitleText: "语音测试", navigationBarBackgroundColor: "#181b24", navigationBarTextStyle: "white" }; mixins = []; data = { showAudioState: false, // 是否显示底部按住说话状态 recorderManager: null, // 录音对象 innerAudioContext: null, // 音频对象 text: "按住 说话", // 按钮文本 options: { duration: 10000, //指定录音的时长,单位 ms sampleRate: 16000, //采样率 numberOfChannels: 1, //录音通道数 encodeBitRate: 96000, //编码码率 format: "mp3", //音频格式,有效值 aac/mp3 frameSize: 50 //指定帧大小,单位 KB }, startPoint: {}, //记录长按录音开始点信息,用于后面计算滑动距离。 touchLengt: 0, // 上滑的距离 audioArr: [ { src: "http://mp3.djwma.com/mp3/爆袭全站欢快节奏感觉那是杠杠滴.mp3", time: 30, state: false }, { src: "http://mp3.djwma.com/mp3/好听的欧美男声 网络流行.mp3", time: 50, state: false } ] // 音频数据数组 }; computed = {}; methods = { // 是否显示底部按住说话 showAudio () { this.showAudioState = !this.showAudioState this.$apply() }, // 触摸按住说话进行录音 handleRecordStart(e) { this.touchLengt = 0; this.startPoint = e.touches[0]; this.text = "松开结束"; this.$apply(); this.recorderManager.start(this.options); //开始录音 this.recorderManager.onStart(() => { console.log("已经开始了哦~"); }); wepy.showToast({ title: "正在录音,上划取消发送", icon: "none", duration: 60000 //先定义个60秒,后面可以手动调用wx.hideToast()隐藏 }); }, // 松开触摸按住说话进行判断是否发送或取消 handleRecordStop() { if (this.touchLengt > 50) { this.recorderManager.stop(); this.recorderManager.onStop(res => { console.log("停止录音", res.tempFilePath); }); this.text = "按住说话"; wepy.hideToast(); //结束录音、隐藏Toast提示框 } else { this.recorderManager.stop(); this.recorderManager.onStop(res => { const { tempFilePath } = res; // 获得临时音频链接 const duration = Math.ceil(res.duration / 1000) // 计算出时长 this.audioArr.push({ // 添加到音频展示列表中 src: tempFilePath, time: duration, state: false }); this.setData({ audioArr: this.audioArr }); // 以下是上传到服务器的代码,如七牛 // let audioURL = '' // API.getQiniuToken().then(data => { // 七牛请求获得token校验 // qiniuUploader.upload(tempFilePath, (res) => { // audioURL = 'https://...(这里写域名)' + res.key // this.audioArr.push({ // src: audioURL, // time: duration, // state: false // }); // this.setData({ // audioArr: this.audioArr // }); // }, (error) => { // console.error('error: ' + JSON.stringify(error)); // }, // { // uptoken: data.token, // region: 'ECN', // 华东区 // key: `slls/audio/${Math.random().toString(36).slice(2,10)}_${Date.parse(new Date())}.mp3` // 音频路径命名 // }, // // (progress) => { // // console.log('上传进度', progress.progress) // // console.log('已经上传的数据长度', progress.totalBytesSent) // // console.log('预期需要上传的数据总长度', progress.totalBytesExpectedToSend) // // }, // ); // }) }); this.text = "开始录音"; wepy.hideToast(); //结束录音、隐藏Toast提示框 } }, // 监听触摸向上滑动距离 handleTouchMove(e) { const moveLenght = e.touches[e.touches.length - 1].clientY - this.startPoint.clientY; //移动距离 if (Math.abs(moveLenght) > 50) { wepy.showToast({ title: "松开手指,取消发送", icon: "none", duration: 60000 }); this.touchLengt = Math.abs(moveLenght); console.log(this.touchLengt); } else { wepy.showToast({ title: "正在录音,上划取消发送", icon: "none", duration: 60000 }); } }, //音频播放 audioPlay(e) { const index = e.currentTarget.dataset.index; const audioArr = this.audioArr; this.innerAudioContext.autoplay = true; this.innerAudioContext.src = audioArr[index].src; // 切换显示状态 for (let i = 0; i < audioArr.length; i++) { audioArr[i].state = false; } audioArr[index].state = true; this.innerAudioContext.play(); //开始监听 this.innerAudioContext.onPlay(() => { this.setData({ audioArr: audioArr }); }); //结束监听 this.innerAudioContext.onEnded(() => { audioArr[index].state = false; this.setData({ audioArr: audioArr }); }); console.log("1", audioArr[index].src); }, // 音频停止 audioStop(e) { const index = e.currentTarget.dataset.index; const audioArr = this.audioArr; //切换显示状态 for (let i = 0; i < audioArr.length; i++) { audioArr[i].state = false; } audioArr[index].state = false; this.innerAudioContext.stop(); //开始监听 this.innerAudioContext.onStop(() => { audioArr[index].state = false; this.setData({ audioArr: audioArr }); }); //结束监听 this.innerAudioContext.onEnded(() => { audioArr[index].state = false; this.setData({ audioArr: audioArr }); }); console.log("2", audioArr); } }; events = {}; onLoad(options) { this.recorderManager = wepy.getRecorderManager(); this.innerAudioContext = wepy.createInnerAudioContext(); this.$apply(); } } </script>
附带七牛上传的JS如下:
// created by gpake (function() { var config = { qiniuRegion: '', qiniuImageURLPrefix: '', qiniuUploadToken: '', qiniuUploadTokenURL: '', qiniuUploadTokenFunction: null, qiniuShouldUseQiniuFileName: false } module.exports = { init: init, upload: upload, } // 在整个程序生命周期中,只需要 init 一次即可 // 如果需要变更参数,再调用 init 即可 function init(options) { config = { qiniuRegion: '', qiniuImageURLPrefix: '', qiniuUploadToken: '', qiniuUploadTokenURL: '', qiniuUploadTokenFunction: null, qiniuShouldUseQiniuFileName: false }; updateConfigWithOptions(options); } function updateConfigWithOptions(options) { if (options.region) { config.qiniuRegion = options.region; } else { console.error('qiniu uploader need your bucket region'); } if (options.uptoken) { config.qiniuUploadToken = options.uptoken; } else if (options.uptokenURL) { config.qiniuUploadTokenURL = options.uptokenURL; } else if(options.uptokenFunc) { config.qiniuUploadTokenFunction = options.uptokenFunc; } if (options.domain) { config.qiniuImageURLPrefix = options.domain; } config.qiniuShouldUseQiniuFileName = options.shouldUseQiniuFileName } function upload(filePath, success, fail, options, progress, cancelTask) { if (null == filePath) { console.error('qiniu uploader need filePath to upload'); return; } if (options) { updateConfigWithOptions(options); } if (config.qiniuUploadToken) { doUpload(filePath, success, fail, options, progress, cancelTask); } else if (config.qiniuUploadTokenURL) { getQiniuToken(function() { doUpload(filePath, success, fail, options, progress, cancelTask); }); } else if (config.qiniuUploadTokenFunction) { config.qiniuUploadToken = config.qiniuUploadTokenFunction(); if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) { console.error('qiniu UploadTokenFunction result is null, please check the return value'); return } doUpload(filePath, success, fail, options, progress, cancelTask); } else { console.error('qiniu uploader need one of [uptoken, uptokenURL, uptokenFunc]'); return; } } function doUpload(filePath, success, fail, options, progress, cancelTask) { if (null == config.qiniuUploadToken && config.qiniuUploadToken.length > 0) { console.error('qiniu UploadToken is null, please check the init config or networking'); return } var url = uploadURLFromRegionCode(config.qiniuRegion); var fileName = filePath.split('//')[1]; if (options && options.key) { fileName = options.key; } var formData = { 'token': config.qiniuUploadToken }; if (!config.qiniuShouldUseQiniuFileName) { formData['key'] = fileName } var uploadTask = wx.uploadFile({ url: url, filePath: filePath, name: 'file', formData: formData, success: function (res) { var dataString = res.data if(res.data.hasOwnProperty('type') && res.data.type === 'Buffer'){ dataString = String.fromCharCode.apply(null, res.data.data) } try { var dataObject = JSON.parse(dataString); //do something var imageUrl = config.qiniuImageURLPrefix + '/' + dataObject.key; dataObject.imageURL = imageUrl; // console.log(dataObject); if (success) { success(dataObject); } } catch(e) { console.log('parse JSON failed, origin String is: ' + dataString) if (fail) { fail(e); } } }, fail: function (error) { console.error(error); if (fail) { fail(error); } } }) uploadTask.onProgressUpdate((res) => { progress && progress(res) }) cancelTask && cancelTask(() => { uploadTask.abort() }) } function getQiniuToken(callback) { wx.request({ url: config.qiniuUploadTokenURL, success: function (res) { var token = res.data.uptoken; if (token && token.length > 0) { config.qiniuUploadToken = token; if (callback) { callback(); } } else { console.error('qiniuUploader cannot get your token, please check the uptokenURL or server') } }, fail: function (error) { console.error('qiniu UploadToken is null, please check the init config or networking: ' + error); } }) } function uploadURLFromRegionCode(code) { var uploadURL = null; switch(code) { case 'ECN': uploadURL = 'https://up.qbox.me'; break; case 'NCN': uploadURL = 'https://up-z1.qbox.me'; break; case 'SCN': uploadURL = 'https://up-z2.qbox.me'; break; case 'NA': uploadURL = 'https://up-na0.qbox.me'; break; case 'ASG': uploadURL = 'https://up-as0.qbox.me'; break; default: console.error('please make the region is with one of [ECN, SCN, NCN, NA, ASG]'); } return uploadURL; } })();
以上就是全部代码,干货。不多说。