第三章 “我要点爆”微信小程序云开发之点爆方式页面和爆炸之音页面制作
点爆方式选择页面制作
在app.json中配置页面路径增加selectbao点爆方式选择,编译创建页面文件,点爆方式选择页面通过单选按钮组选择跳转到相应的点爆页面。
<view class="the_header">
<text>选择点爆方式</text>
<image src="/images/fencun.png"></image>
</view>
<view class="select_check">
<radio-group bindchange="selectway">
<radio checked='true' value='爆炸之音'>爆炸之音</radio>
<radio value='疯狂点击'>疯狂点击</radio>
<radio value='糖果点爆'>糖果点爆</radio>
</radio-group>
</view>
<view class="select_button">
<button bindtap="next">下一步</button>
</view>
给单选按钮组增加bindchange属性的方法,控制获取所选项,当点击下一步时触发点击事件,通过next方法判断跳转不同的页面。
Page({
data: {
wway: '爆炸之音'
},
selectway: function (e) {
this.setData({
wway: e.detail.value
})
},
next: function () {
let wway = this.data.wway
wx.setStorageSync('wway', wway)
if (wway == '爆炸之音') {
wx.navigateTo({
url: '../selecty/selecty'
})
} else if (wway == '疯狂点击') {
wx.navigateTo({
url: '../selectd/selectd'
})
} else {
wx.navigateTo({
url: '../selectt/selectt'
})
}
},
onLoad: function () {
wx.setNavigationBarTitle({
title: '点爆方式'
})
}
})
运行效果图:
爆炸之音方式制作
在app.json中增加爆炸之音录音页面selecty和爆炸之音确认页面selectyok,在selecty中我们进行录音操作,在selectyok中我们进行语音试听和爆文发布操作。
selecty.wxml中设置一个button录音按钮,并使用bindtouchstart和bindtouchend属性进行录音控制,与语音记录相同。
<view class="the_header">
<text>爆炸之音</text>
<image src="/images/fencun.png"></image>
</view>
<view class="button1">
<button bindtouchstart="touchdown" bindtouchend="touchup"><image src="/images/yuyin5.png"></image></button>
</view>
在录音过程中调用帧文件监听的回调事件RecorderManager.onFramRecorded(function callback)对帧文件进行监听,用sum记录帧文件的大小和,用sumt记录帧文件的个数。
//监听帧文件
recorderManager.onFrameRecorded((res) => {
const { frameBuffer } = res
sum += frameBuffer.byteLength
sumt++
})
在停止录音后,使用下方算法对热度值进行简单计算。
if (sumt > 10) {
var wn = (sum - 1500) / (sumt - 1) - 2300
} else {
var wn = (sum - 1500) / (sumt - 1) - 3000
}
在云开发控制台存储中新建baovoice文件夹用于保存爆炸之音所录的语音,同时新建云函数updateBaovoice,云函数用于修改用户users表中baovoice的数量值,用于记录用户所录入爆炸之音的个数和对语音文件进行命名。云函数创建并完成配置与编写后,上传并部署。
updateBaovoice/index.js
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
//声明数据库
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
//取得传过来的参数
var baovoice = event.baovoice, openId = event.openId;
//云函数,更新
try {
return await db.collection('users').where({
_openid: openId
}).update({
data: {
baovoice: baovoice
},
success: res => {
console.log('云函数成功')
},
fail: e => {
console.error(e)
}
})
} catch (e) {
console.error(e)
}
}
js中对语音进行操作,完成录音后跳转到爆炸之音确认页面selectyok
//录音管理
const recorderManager = wx.getRecorderManager()
var tempFilePath
var sum = 0
var sumt = 0;
Page({
data: {
},
//按钮点下开始录音
touchdown: function () {
const options = {
duration: 300000,//指定录音的时长,单位 ms
sampleRate: 16000,//采样率
numberOfChannels: 1,//录音通道数
encodeBitRate: 96000,//编码码率
format: 'mp3',//音频格式,有效值 aac/mp3
frameSize: 5 //指定帧大小,单位 KB
}
//监听帧文件
recorderManager.onFrameRecorded((res) => {
const { frameBuffer } = res
sum += frameBuffer.byteLength
sumt++
})
//开始录音
recorderManager.start(options);
recorderManager.onStart(() => {
console.log('recorder start')
})
//错误回调
recorderManager.onError((res) => {
console.log(res);
})
},
//停止录音
touchup: function () {
wx.showLoading({
title: '',
mask: true
})
recorderManager.stop();
if (sumt > 10) {
var wn = (sum - 1500) / (sumt - 1) - 2300
} else {
var wn = (sum - 1500) / (sumt - 1) - 3000
}
wx.setStorageSync('wnum', parseInt(wn))
sum = 0
sumt = 0
recorderManager.onStop((res) => {
this.tempFilePath = res.tempFilePath
console.log('停止录音', res.tempFilePath)
const { tempFilePath } = res
//查询用户已有语音,记录,并为文件赋值
//获取数据库引用
const db = wx.cloud.database()
const _ = db.command
//查找数据库,获得用户语音数量
db.collection('users').where({
_openid: wx.getStorageSync('openId')
}).get({
success(res) {
// res.data 是包含以上定义的记录的数组
console.log('查询用户:', res)
//将名字定为id号+个数号+.mp3
var newbaovoice = res.data[0].baovoice + 1
var baofilename = wx.getStorageSync('openId') + newbaovoice + '.mp3'
//调用云函数,修改爆语音数量,向云函数传值
wx.cloud.callFunction({
name: 'updateBaovoice',
data: {
openId: wx.getStorageSync('openId'),
baovoice: newbaovoice
},
success: res => {
//上传录制的音频到云
wx.cloud.uploadFile({
cloudPath: 'baovoice/' + baofilename,
filePath: tempFilePath, // 文件路径
success: res => {
console.log(res.fileID)
//保存点爆语音fileID,方便后面播放
wx.setStorageSync('fileIDd', res.fileID)
//将数据保存到本地
wx.setStorageSync('baofilename', baofilename)
wx.setStorageSync('ybaotempFilePath', tempFilePath)
//关闭加载
wx.hideLoading()
//跳转到听语音的页面
wx.navigateTo({
url: '../selectyok/selectyok'
})
},
fail: err => {
// handle error
console.error(err)
}
})
}
})
},
fail: err => {
}
})
})
setTimeout((() => {
//关闭加载
wx.hideLoading()
}), 4000)
},
onLoad: function () {
wx.setNavigationBarTitle({
title: '爆炸之音'
})
}
})
爆炸之音确认页面
<view class="the_header">
<text>爆炸之音</text>
<image src="/images/fencun.png"></image>
</view>
<view class="button1">
<image src="/images/yuyin6.png" bindtap="play"></image>
<text>爆炸热度:{{wtemperature}}</text>
</view>
<view class="selectd_button">
<button bindtap="add">确定</button>
</view>
<view class="the_btn">
<button bindtap="seal">封存</button>
</view>
新建爆文信息集合bao和封存信息集合seal,两个集合的结构相同,如下:
字段名 | 数据类型 | 主键 | 非空 | 描述 |
---|---|---|---|---|
_id | String | 是 | 是 | ID |
_openid | String | 是 | 用户唯一标识 | |
avaterUrl | String | |||
gender | String | 性别 | ||
province | String | 地区 | ||
temperature | number | 热度值 | ||
userId | String | ID | ||
username | String | 用户名 | ||
wmood | String | 心情颜色(文本) | ||
text | String | 爆文文本 | ||
time | String | 操作时间 | ||
wway | String | 点爆方式(文本) | ||
ymood | String | 心情颜色(语音) | ||
yway | String | 点爆方式(语音) | ||
filename | String | 语音文件名 | ||
filelDd | String | 爆炸之音地址 | ||
baofilename | String | 爆炸之音文件名 |
js模块加载,在miniprogram下新建utils文件,同时在utils文件下新建一个utils.js文件,用于创建事件函数
utils.js
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formaDate = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
return [year, month, day].map(formatNumber).join('-')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
module.exports = {
formatTime: formatTime,
formaDate: formaDate
}
js模块加载require方法,引用utils.js文件,获取一个util对象,调用对象中的formatTime方法来获取当前时间。
var util = require('../../utils/utils.js');
selectyok.js中我们完成录音的试听,同时通过爆文记录页面保存在本地的wy变量值,判断是文本记录还是语音记录,从而设置不同的data属性列表,完整的selectyok.js代码如下:
var util = require('../../utils/utils.js');
//音频组件控制
const innerAudioContext = wx.createInnerAudioContext()
const db = wx.cloud.database()
const _ = db.command;
Page({
data: {
wtemperature: 0,
theplay: true
},
//播放声音
play: function () {
if (this.data.theplay) {
this.setData({
theplay: false
})
innerAudioContext.autoplay = true
innerAudioContext.src = wx.getStorageSync('ybaotempFilePath'),
innerAudioContext.onPlay(() => {
console.log('开始播放')
}),
innerAudioContext.onEnded(() => {
this.setData({
theplay: true
})
})
innerAudioContext.onError((res) => {
console.log(res.errMsg)
console.log(res.errCode)
})
}
},
//页面被卸载时被执行
onUnload: function () {
innerAudioContext.stop();
},
//当点击确认后如果语音在播放则关闭
onHide: function () {
innerAudioContext.stop()
},
//将数据写入数据库
add: function () {
wx.showLoading({
title: '',
mask: true
})
var wy = wx.getStorageSync("wy")
if(wy == "w"){
var data = {
userId: wx.getStorageSync('userId'),
openId: wx.getStorageSync('openId'),
username: wx.getStorageSync('username'),
gender: wx.getStorageSync('gender'),
province: wx.getStorageSync('province'),
avaterUrl: wx.getStorageSync('avater'),
text: wx.getStorageSync('wtext'),
wmood: wx.getStorageSync('wmood'),
wway: wx.getStorageSync('wway'),
baofilename: wx.getStorageSync('baofilename'),
fileIDd: wx.getStorageSync('fileIDd'),
temperature: wx.getStorageSync('wnum'),
time: util.formatTime(new Date())
}
}else{
var data = {
userId: wx.getStorageSync('userId'),
openId: wx.getStorageSync('openId'),
username: wx.getStorageSync('username'),
gender: wx.getStorageSync('gender'),
province: wx.getStorageSync('province'),
avaterUrl: wx.getStorageSync('avater'),
filename: wx.getStorageSync('filename'),
fileIDy: wx.getStorageSync('fileIDy'),
ymood: wx.getStorageSync('ymood'),
yway: wx.getStorageSync('wway'),
baofilename: wx.getStorageSync('baofilename'),
fileIDd: wx.getStorageSync('fileIDd'),
temperature: wx.getStorageSync('wnum'),
time: util.formatTime(new Date())
}
}
db.collection('bao').add({
data: data,
success: res => {
console.log('bao存入成功')
wx.showToast({
title: '点爆成功',
})
setTimeout(() => {
wx.navigateTo({
url: '../success/success'
})
}, 1000)
wx.hideLoading()
}
})
},
//封存
seal: function () {
wx.showLoading({
title: '',
mask: true
})
var wy = wx.getStorageSync("wy")
if (wy == "w") {
var data = {
userId: wx.getStorageSync('userId'),
openId: wx.getStorageSync('openId'),
username: wx.getStorageSync('username'),
gender: wx.getStorageSync('gender'),
province: wx.getStorageSync('province'),
avaterUrl: wx.getStorageSync('avater'),
text: wx.getStorageSync('wtext'),
wmood: wx.getStorageSync('wmood'),
wway: wx.getStorageSync('wway'),
baofilename: wx.getStorageSync('baofilename'),
fileIDd: wx.getStorageSync('fileIDd'),
temperature: wx.getStorageSync('wnum'),
time: util.formatTime(new Date())
}
} else {
var data = {
userId: wx.getStorageSync('userId'),
openId: wx.getStorageSync('openId'),
username: wx.getStorageSync('username'),
gender: wx.getStorageSync('gender'),
province: wx.getStorageSync('province'),
avaterUrl: wx.getStorageSync('avater'),
filename: wx.getStorageSync('filename'),
fileIDy: wx.getStorageSync('fileIDy'),
ymood: wx.getStorageSync('ymood'),
yway: wx.getStorageSync('wway'),
baofilename: wx.getStorageSync('baofilename'),
fileIDd: wx.getStorageSync('fileIDd'),
temperature: wx.getStorageSync('wnum'),
time: util.formatTime(new Date())
}
}
db.collection('seal').add({
data: data,
success: res => {
console.log('seal存入成功')
wx.showToast({
title: '封存成功',
})
setTimeout(() => {
wx.navigateTo({
url: '../success/success'
})
}, 1000)
wx.hideLoading()
}
})
},
onLoad: function () {
wx.setNavigationBarTitle({
title: '爆炸之音'
})
let temperature = wx.getStorageSync('wnum')
this.setData({
wtemperature: temperature
})
}
})
效果图:(可以看到爆炸热度为-1500,原因是在开发者工具的模拟器中所进行的录音功能对于录音文件与移动端格式不同,所以热度值无法计算)
创建爆文操作成功后提示页success,success页面只显示一个成功的提示文字,然后通过延时定时器自动或手动点击跳转到首页世界页面。
success.wxml
<view class="the_header">
<text>点爆成功</text>
<image src="/images/fencun.png"></image>
</view>
<view class="button1" bindtap="goindex">
<image src="/images/baook.png"></image>
</view>
让导航页面重新加载,跳转导航的页面可以通过switchTab,但默认情况是不会重新加载数据的,通过这三行代码,当进入首页index时,让页面重新加载调用页面的onLoad方法,达到刷新数据的作用。
var page = getCurrentPages().pop();
if (page == undefined || page==null) return;
page.onLoad();
success.js完整代码:
Page({
data: {
},
goindex: function () {
wx.switchTab({
url: '../index/index',
})
},
//监听页面自动跳转
onShow: function () {
setTimeout(() => {
wx.reLaunch({
url: '../index/index',
success: function (e) {
var page = getCurrentPages().pop();
if (page == undefined || page == null) return;
page.onLoad();
}
})
}, 2000)
},
onLoad: function () {
wx.setStorageSync('wtext', '')
wx.setStorageSync('wmood', 'red')
wx.setStorageSync('wway', '1')
wx.setStorageSync('wnum', 0)
}
})
现在我们可以进行一次完整的爆炸之音点爆方式的演示:
数据库中成功增加数据,说明点爆与发布成功。