5分钟
任务 4 小程序页面实现
任务目的
编写小程序界面和必要的交互脚本。
任务步骤
1.删除小程序自动生成的多余页面
将 miniprogram 文件夹下小程序自动生成的多余的页面进行删除,包括:
- components 文件夹
- images 文件夹下所有的图片(保留 images 文件夹)
- pages 文件夹下除 index 文件夹之外的其他文件夹。
可以在微信开发者工具中删除,也可以直接进入硬盘进行删除。
2.改写小程序配置文件
点击 miniprogram 文件夹下的 app.json,将 app.json 改写为
{
"pages": [
"pages/index/index"
],
"window": {
"backgroundColor": "#F6F6F6",
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#F6F6F6",
"navigationBarTitleText": "趣味复读机器人",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json",
"style": "v2"
}
小程序的配置比较简单,主要把多余的页面删除,仅留 index 页面,修改默认的主题名即可。
3.修改 index 页面
下载本次小程序开发所需的图片资源,点击此处下载。将下载后的文件解压放到 miniprogram/images 文件夹下。
将 index 文件夹下默认带的 user-unlogin.png 删除。将 index.wxml 替换成以下代码。
<view class="flex-row" style="display:flex;">
<checkbox-group name="checkbox" class="check">
<label bindtap='changeVoiceType' wx:for="{{voiceTypes}}" wx:key="index" data-voiceType="{{item.num}}" class='{{item.checked?"is_checked":""}}'>
<checkbox hidden='false' /> {{item.name}}
</label>
</checkbox-group>
</view>
<scroll-view upper-threshold="100" scroll-into-view="{{toView}}" scroll-top="{{scrollTop}}" scroll-y="true" enable-back-to-top="true" style="height: {{scroll_height}}px;" class="message-list">
<!-- 每一行 -->
<view class="row" wx:for="{{message_list}}" wx:key="index" id="row_{{index}}">
<!-- 头像与内容文本 -->
<view class="body" style="flex-flow: {{item.myself == 0 ? 'row' : 'row-reverse'}}">
<view class="avatar-container">
<image class="avatar" src="{{item.head_img_url}}" />
</view>
<!-- 画三角箭头 -->
<view class="triangle" style="{{item.myself == 1 ? 'right: 140rpx; background: #7ECB4B' : 'left: 140rpx;'}}"></view>
<view class="content" style="{{item.myself == 1 ? 'background: #7ECB4B' : ''}}">
<view bindtap="playVoice" data-src="{{item.content}}" style="width:40px">
<image class="ico" src="/images/voice.png"/>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="hud-container" wx:if="{{status != state.normal}}">
<view class="hud-background"></view>
<view class="hud-body">
<image src="/images/mic.png" />
<view class="tip {{status == state.cancel ? 'warning' : ''}}">{{tips[status]}}</view>
</view>
</view>
<view class="reply">
<view class="opration-area">
<button class="voice-button" bindlongpress="record" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd">{{tips[status]}}</button>
</view>
</view>
将 index 文件夹下 index.wxss 替换成以下代码
/*聊天记录*/
.message-list {
/*margin-bottom: 54px;*/
background: rgb(235, 235, 235);
}
/*单元行*/
.row {
display: flex;
flex-direction: column;
margin: 0 30rpx;
}
/*日期*/
.datetime {
font-size: 10px;
padding: 10px 0;
color: #999;
text-align: center;
}
/*主体*/
.body {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
width: 100%;
margin-top: 10px;
}
/*头像容器*/
.body.avatar-container {
width: 20%;
}
/*头像*/
.body .avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
margin: 0 20rpx;
}
/*文本消息*/
.body .content {
font-size: 16px;
background: #fff;
border-radius: 5px;
padding: 10px;
line-height: 22px;
margin-bottom: 10px;
}
/* 三角箭头 */
.body .triangle {
background: white;
width: 20rpx;
height: 20rpx;
margin-top: 26rpx;
transform: rotate(45deg);
position: absolute;
}
/*图片消息*/
.picture {
width: 160px;
}
/*回复框*/
.reply {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
position: fixed;
bottom: 0;
width: 100%;
height: 54px;
border-top: 1px solid rgb(215, 215, 215);
background: rgb(245, 245, 245);
}
.reply .voice-image {
width: 25px;
height: 25px;
margin-left: 3%;
}
/*文本输入或语音录入*/
.reply .opration-area {
flex: 1;
padding: 8px;
}
/*按住说话button*/
.voice-button {
height: 36px;
color: #818181;
font-size: 14px;
line-height: 24px;
width: 300px !important;
background: #F9F9F9
}
/*悬浮提示框*/
.hud-container {
position: fixed;
width: 150px;
height: 150px;
left: 50%;
top: 50%;
margin-left: -75px;
margin-top: -75px;
}
/*背景层*/
.hud-background {
position: absolute;
width: 100%;
height: 100%;
background: #999;
opacity: .8;
z-index: 11;
border-radius: 10px;
}
/*悬浮框主体*/
.hud-body {
position: relative;
width: 100%;
height: 100%;
z-index: 19;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
/*图标*/
.hud-body image {
margin-top: 20px;
width: 80px;
height: 80px;
}
/*文字*/
.hud-body .tip {
color: #fff;
text-align: center;
width: 90%;
line-height: 34px;
margin: 0 auto;
margin-bottom: 10px;
}
.hud-body .warning {
background: #cc3333;
border-radius: 5px;
}
.ico{
width: 43rpx;
height: 50rpx;
float: left;
}
label{
border:2rpx solid #aaaaaa;
}
.check {
display:flex;
flex-wrap:wrap;
justify-content:space-around;
}
.check label {
color: #818181;
width: 175rpx;
height: 60rpx;
border-radius: 8rpx;
display: flex;
align-items: center;
margin: 0 5rpx;
justify-content: center;
margin-top: 20rpx;
font-size: 30rpx;
}
.is_checked {
background: #7ECB4B;
color: #fff !important;
border: 2rpx solid #fff;
}
.is_checked>checkbox {
color: red;
}
将 index 文件夹下 index.js 替换成以下代码
Page({
data: {
message_list: [],
scroll_height: wx.getSystemInfoSync().windowHeight - 54,
page_index: 0,
cancel: false,
status: 0,
tips: ['按住 说话', '松开 结束', '取消 发送'],
voiceTypes: [{
name:'亲和女声',
num:0,
checked:true
},{
name:'亲和男声',
num:1,
checked: false
},{
name:'成熟男声',
num:2,
checked: false
},{
name:'温暖女声',
num:4,
checked: false
}],
voiceType:0,
state: {
'normal': 0,
'pressed': 1,
'cancel': 2
},
toView: '',
currentText: ''
},
//录音功能,后期改写
record: function () {
},
//录音结束后将会发送语音到界面,后期改写
stop: function () {
this.sendVoice("tempfile",1)
this.sendVoice("tempfile", 0)
},
touchStart: function (e) {
// 触摸开始
var startY = e.touches[0].clientY;
// 记录初始Y值
this.setData({
startY: startY,
status: this.data.state.pressed
});
},
touchMove: function (e) {
// 触摸移动
var movedY = e.touches[0].clientY;
var distance = this.data.startY - movedY;
this.setData({
status: distance > 50 ? this.data.state.cancel : this.data.state.pressed
});
},
touchEnd: function (e) {
// 触摸结束
var endY = e.changedTouches[0].clientY;
var distance = this.data.startY - endY;
this.setData({
cancel: distance > 50 ? true : false,
status: this.data.state.normal
});
// 不论如何,都结束录音
this.stop();
},
scrollToBottom: function () {
this.setData({
toView: 'row_' + (this.data.message_list.length - 1)
});
},
sendVoice: function (tempUrl, num) {
var message_list = this.data.message_list;
var message = {
myself: num,
head_img_url: '/images/userimg.jpg',
content: tempUrl,
};
message_list.push(message);
this.setData({
message_list: message_list
})
this.scrollToBottom()
setTimeout(() => {
wx.hideLoading();
}, 500)
},
changeVoiceType:function(e){
let voiceType = e.currentTarget.dataset.voicetype;
let arrys = this.data.voiceTypes;
for(let i = 0;i<arrys.length;i++){
if(arrys[i].num == voiceType){
arrys[i].checked = true
}else{
arrys[i].checked = false
}
}
this.setData({
voiceTypes: arrys,
voiceType:voiceType
})
},
//播放语音功能,后期填写功能
playVoice:function(){
}
})
替换完毕后,保存代码,或者点击【编译】按钮,可以从模拟器中看到效果
学员评价