import { getActivityInfo, getShareText, saveActivity } from '~/api/activity' import { actionRecord } from '~/api/global' /*微信录音*/ let recorderManager = wx.getRecorderManager(); let dsq Page({ /** * 页面的初始数据 */ data: { // 'before录制前, process 录制中,after录制后' state: 'before', tens: 3, bits: 0, configure: {}, avatar: '', // 本地录音地址 tempFilePath: '', // 线上录音地址 audioPath: '', uploadState: false, focusTo: false, focusFrom: false, // 此id保存模板使用 id: '', greeting: [], greetingCard: null, userAudioState: false, // 当前音频播放时长 playTime: '00:00', endTime: '00:00', vProgress: 0 }, async onLoad(options) { let configure = await getActivityInfo(options.id) wx.setNavigationBarTitle({ title: configure.title, }) this.setData({ configure, avatar: configure.photoText, id: options.id, greeting: configure.greeting.split('\n'), tens: configure.bgMusicLength[0], bits: configure.bgMusicLength[1] }) this.innerAudioContext = wx.createInnerAudioContext(); this.innerAudioContext.src = configure.bgMusic; // 这里可以是录音的临时路径 // 录音授权 wx.getSetting({ success(res) { if (!res.authSetting['scope.record']) { wx.authorize({ scope: 'scope.record', success() { // 用户已经同意小程序使用录音功能,后续调用接口不会弹窗询问 } }) } } }) await actionRecord({ action: 'NEW_YEAR_ACTIVITY_CHOOSE_TEMPLATE', targetContent: options.id }) }, showActionSheet() { wx.chooseMedia({ count: 1, mediaType: ['image'], sizeType: ['compressed'], // 必须放在 数组里面才有效; original 原图;compressed 压缩图 sourceType: ['album', 'camera'], camera: 'back', success: (res) => { this.cropper = this.selectComponent("#yeyouzi-cropper"); this.cropper.init({ imgPath: res.tempFiles[0].tempFilePath, //imgPath是需要裁剪图片的图片路径,只支持本地或临时路径 success: (res) => { this.changeAvatar(res) }, fail(error) { console.log(error) //有两种:cancel代表点击了叉,fail代表wx.canvasToTempFilePath生成图片失败 } }); } }) }, async changeAvatar(e) { let res = await this.uploadFile(e) this.setData({ avatar: res }) }, play() { if (this.data.state == 'before') { this.innerAudioContext.play(); this.innerAudioContext.onEnded((res) => { this.setData({ userAudioState: false }) }); this.setData({ state: 'process' }) let countDown = Number(this.data.configure.bgMusicLength) // 倒计时 this.dsq = setInterval(item => { // 倒计时结束 if (countDown == 1) { this.stopRecording() } if (countDown % 10 == 0) { this.setData({ tens: --this.data.tens, bits: 9 }) } else { this.setData({ bits: --this.data.bits }) } --countDown }, 1000) const options = { sampleRate: 44100, //采样率 numberOfChannels: 1, //录音通道数 encodeBitRate: 192000, //编码码率 format: 'mp3', //音频格式,有效值aac/mp3 frameSize: 50 //指定帧大小,单位 KB }; //开始录音,在开始录音回调中feed音频片 recorderManager.start(options); //监听录音结束事件 recorderManager.onStop((res) => { this.setData({ tempFilePath: res.tempFilePath, }); this.uploadAudio(res.tempFilePath) }); } else { this.stopRecording() } }, stopRecording() { clearInterval(this.dsq) this.innerAudioContext.stop(); recorderManager.stop(); this.setData({ state: 'after', tens: this.data.configure.bgMusicLength[0], bits: this.data.configure.bgMusicLength[1] }) }, uploadAudio(recordSource) { this.setData({ uploadState: true }); const uploadTask = wx.uploadFile({ url: 'https://reader-api.ai160.com//file/upload', filePath: recordSource, name: '朗读录音', header: { uid: wx.getStorageSync('uid') }, success: (res) => { const formateRes = JSON.parse(res.data); let audioPath = formateRes.data; this.setData({ audioPath }) this.uploadActivity() }, }) }, // 上传贺卡 async uploadActivity() { this.createActivityImg('upload').then(async res => { let cardUrl = await this.uploadFile(res) let data = { audioPath: this.data.audioPath, // 生成贺卡图片地址 cardUrl, toText: this.data.configure.toText, fromText: this.data.configure.fromText, templateId: this.data.id } let greetingCard = await saveActivity(data) this.setDuration('endTime', greetingCard.duration) this.setData({ greetingCard, uploadState: false }) await actionRecord({ action: 'NEW_YEAR_ACTIVITY_GENERATE_TEMPLATE', targetContent: this.data.id }) }) }, playUserAudio() { if (!this.innerAudioContext) { this.innerAudioContext = wx.createInnerAudioContext(); } if (this.data.userAudioState) { this.innerAudioContext.stop(); this.setData({ userAudioState: false }) } else { this.innerAudioContext.src = this.data.greetingCard.audioPath; this.innerAudioContext.onTimeUpdate(() => { this.setDuration('playTime', this.innerAudioContext.currentTime) let vProgress = Math.ceil((Math.ceil(this.innerAudioContext.currentTime) / this.innerAudioContext.duration) * 100) this.setData({ vProgress: vProgress < 96 ? vProgress : 100 }) }) this.innerAudioContext.play(); this.setData({ userAudioState: true }) } }, bindKeyInput(e) { if (e.currentTarget.dataset.type == 'from') { this.setData({ 'configure.fromText': e.detail.value }) } else if (e.currentTarget.dataset.type == 'to') { this.setData({ 'configure.toText': e.detail.value }) } }, focusInput({ currentTarget }) { if (currentTarget.dataset.input == 'from') { this.setData({ focusFrom: true }) } else { this.setData({ focusTo: true }) } }, // 上传图片 uploadFile(filePath) { return new Promise((resolve, reject) => { wx.uploadFile({ url: 'https://reader-api.ai160.com/file/upload', filePath, name: '头像', header: { uid: wx.getStorageSync('uid') }, success: (res) => { const result = JSON.parse(res.data).data; resolve(result) } }) }) }, // 生成活动图片 createActivityImg(createType = 'share') { return new Promise(async (resolve, reject) => { if (createType == 'share') { let title = await getShareText({ cardReadId: this.data.greetingCard.id }) resolve({ title, path: `/pages/greeting/index?uid=${wx.getStorageSync('uid')}&cardId=${this.data.greetingCard.id}`, imageUrl: this.data.greetingCard.cardUrl }) } let context = wx.createSelectorQuery(); context .select('#share') .fields({ node: true, size: true }).exec((res) => { const canvas = res[0].node; const ctx = canvas.getContext('2d'); const dpr = wx.getSystemInfoSync().pixelRatio; canvas.width = res[0].width * dpr; canvas.height = res[0].height * dpr; ctx.scale(dpr, dpr); let avatar = canvas.createImage(); avatar.src = this.data.avatar avatar.onload = () => { ctx.drawImage(avatar, this.data.configure.templateBase.photoLeft / 2, this.data.configure.templateBase.photoTop / 2, this.data.configure.templateBase.photoWidth / 2, this.data.configure.templateBase.photoHeight / 2); let bgImg = canvas.createImage(); bgImg.src = this.data.configure.bgImg bgImg.onload = () => { ctx.drawImage(bgImg, 0, 0, 375, 300); ctx.font = `${this.data.configure.fromFontSize/2}px PingFang`; ctx.fillStyle = `${this.data.configure.toColor}`; let toLeft = 0 if (this.data.configure.toTextAlign == 'left') { toLeft = this.data.configure.templateBase.toLeft / 2 } else if (this.data.configure.toTextAlign == 'right') { toLeft = this.data.configure.templateBase.toLeft / 2 + (this.data.configure.templateBase.toWidth / 2 - ctx.measureText(this.data.configure.toText).width) } else if (this.data.configure.toTextAlign == 'center') { toLeft = this.data.configure.templateBase.toLeft / 2 + ((this.data.configure.templateBase.toWidth / 2 - ctx.measureText(this.data.configure.toText).width) / 2) } ctx.fillText(this.data.configure.toText, toLeft, this.data.configure.templateBase.toTop / 2 + this.data.configure.fromFontSize / 2) ctx.fillStyle = `${this.data.configure.fromColor}`; let fromLeft = 0 if (this.data.configure.fromTextAlign == 'left') { fromLeft = this.data.configure.templateBase.fromLeft / 2 } else if (this.data.configure.fromTextAlign == 'right') { fromLeft = this.data.configure.templateBase.fromLeft / 2 + (this.data.configure.templateBase.fromWidth / 2 - ctx.measureText(this.data.configure.fromText).width) } else if (this.data.configure.fromTextAlign == 'center') { fromLeft = this.data.configure.templateBase.fromLeft / 2 + ((this.data.configure.templateBase.fromWidth / 2 - ctx.measureText(this.data.configure.fromText).width) / 2) } ctx.fillText(this.data.configure.fromText, fromLeft, this.data.configure.templateBase.fromTop / 2 + this.data.configure.toFontSize / 2) setTimeout(() => { wx.canvasToTempFilePath({ canvas: canvas, success(res) { resolve(res.tempFilePath) }, fail(res) { reject() } }, this) }, 1000) } } }) }) }, onShareAppMessage({ from, }) { if (from == 'button') { actionRecord({ action: 'NEW_YEAR_ACTIVITY_SEND_BLESSING', }) const promise = new Promise(resolve => { this.createActivityImg().then(res => { resolve(res) }) }) return { title: '请欣赏我的课文朗读作品,点赞+评论。', path: `/pages/index/index?uid=${wx.getStorageSync('uid')}`, imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png', promise } } else { return { title: '课文朗读,从未如此有趣。', path: `/pages/index/index?uid=${wx.getStorageSync('uid')}`, imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/shareContent.png' } } }, onShareTimeline() { return { title: '拜年还能这么玩?语音贺卡超有趣,点我开玩!', query: `uid=${wx.getStorageSync('uid')}&id=${this.data.id}`, imageUrl: 'http://reader-wx.ai160.com/images/reader/v3/xkx_logo.jpg' } }, // 设置时间文案 setDuration(label, s) { let t = ''; s = Math.ceil(s); if (s > -1) { let min = Math.floor(s / 60) % 60; let sec = s % 60; if (min < 10) { t += "0"; } t += min + ":"; if (sec < 10) { t += "0"; } t += sec; } this.setData({ [label]: t, }) }, onHide() { recorderManager.stop() this.innerAudioContext.stop() }, onUnload() { recorderManager.stop() this.innerAudioContext.stop() } })