第5章
视图容器组件
通过前面内容的学习,读者对小程序有了一个大致的了解,包括组成小程序的各个文件,它们的作用是什么,以及小程序的MINA框架是怎么回事儿。那么从这一章开始,就要开始学习小程序开发的具体细节。
本章的主要内容是对视图容器组件的介绍。视图容器组件,简单来说与HTML中的
标签一样,是小程序页面布局的基础元素,用来组织元素的排布,设置页面的整体布局。当然小程序的视图容器组件要比单纯的丰富得多,掌握了这部分内容,才能更好地设计出页面更加合理美观的小程序。
本章学习目标:
了解Flex布局的方式。
掌握对view组件、scrollview组件、swiper组件、movableview组件、movablearea组件、coverview组件、coverimage组件的使用。
5.1Flex布局和view组件
【任务要求】
新建一个如图51
所示的小程序页面,了解小程序页面组件的基本排列方式。
图51view组件布局
【任务分析】
本任务主要练习的是对view组件和微信小程序所采用的Flex布局的操作。观察图51
可以看到,整个页面的元素整体上来看是纵向排列的,而其中又插入了一个横向布局的三个方块和一个纵向布局的三个方块。因此需要对最外层设置成纵向排列,同时单独设置横向布局的三个方块为横向排列。
【任务操作】
(1) 打开示例项目,并在其app.json文件中新注册一个页面"pages/Chapter_5/5_1_view/5_1_view"。同时修改窗口的配置,使其达到如图51
所示的效果。修改完成后的app.json文件如下。
{
"pages": [
"pages/Chapter_3/mina/mina",
"pages/Chapter_3/page/page",
"pages/Chapter_3/WXML/WXML",
"pages/Chapter_3/WXKEY/WXKEY",
"pages/Chapter_3/WXSS/WXSS",
"pages/Chapter_4/frontend/frontend",
"pages/index/index",
"pages/logs/logs",
"pages/Chapter_5/5_1_view/5_1_view"
],
"window": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "演示",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}
微信小程序实用教程
第
5
章视图容器组件
保存文件并编译项目,让开发者工具自动生成所需的目录和页面。
(2) 修改5_1_view.json文件为如下所示代码,让窗口显示“view”。
{
"navigationBarTitleText": "view"
}
(3) 在5_1_view.wxml文件中写入如下代码,填充页面元素。涉及本任务关键的元素会加粗表示。
view组件
flex-direction: row\n横向布局
flex-direction: column\n纵向布局
(4) 在5_1_view.wxss文件中编写如下代码,实现对页面的样式调整。涉及本任务重点的样式设置将会用粗体显示。
/* pages/Chapter_5/5_1_view/5_1_view.wxss */
page {
background-color: #F8F8F8;
height: 100%;
font-size: 32rpx;
line-height: 1.6;
}
.container {
display: flex;
flex-direction: column;
min-height: 100%;
justify-content: space-between;
font-size: 32rpx;
font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
}
.page-head{
padding: 60rpx 50rpx 80rpx;
text-align: center;
}
.page-head-title{
display: inline-block;
padding: 0 40rpx 20rpx 40rpx;
font-size: 32rpx;
color: #BEBEBE;
}
.page-head-line{
margin: 0 auto;
width: 150rpx;
height: 2rpx;
background-color: #D8D8D8;
}
.page-body {
width: 100%;
flex-grow: 1;
overflow-x: hidden;
}
.page-section{
width: 100%;
margin-bottom: 60rpx;
}
.page-section-title{
font-size: 28rpx;
color: #999999;
margin-bottom: 10rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
.page-section-spacing{
box-sizing: border-box;
padding: 0 80rpx;
}
.flex-wrp{
margin-top: 60rpx;
display:flex;
}
.flex-item{
width: 200rpx;
height: 300rpx;
font-size: 26rpx;
}
.demo-text-1{
position: relative;
align-items: center;
justify-content: center;
background-color: #1AAD19;
color: #FFFFFF;
font-size: 36rpx;
}
.demo-text-1:before{
content: 'A';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.demo-text-2{
position: relative;
align-items: center;
justify-content: center;
background-color: #2782D7;
color: #FFFFFF;
font-size: 36rpx;
}
.demo-text-2:before{
content: 'B';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.demo-text-3{
position: relative;
align-items: center;
justify-content: center;
background-color: #F1F1F1;
color: #353535;
font-size: 36rpx;
}
.demo-text-3:before{
content: 'C';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.flex-item-V{
margin: 0 auto;
width: 300rpx;
height: 200rpx;
}
(5) 在前面的任务中,均是将需要预览的页面放在app.json文件里pages数组的第一项,这样固然方便,但是当需要调试多个页面时,
图52添加编译模式
不停去修改app.json文件也比较麻烦。因此从这一部分起,将使用设置“编译模式”的方式来对页面进行预览。在工具栏中打开“普通编译”下拉框,选择“添加编译模式”(如图52
所示),在弹出的对话框中,给“模式名称”起名为“view”,从“启动页面”下拉框中选择“pages/Chapter_5/5_1_view/5_1_view”为启动页面(如图53
所示)。
图53自定义编译条件将页面5_1_view设置为启动页面
(6) 如图54
所示,选择刚刚新建的view编译模式,单击“编译”按钮,便可以在界面左边的模拟器中查看到刚刚编写的5_1_view页面的效果了。
图54使用自定义编译模式编译
【相关知识】
要想学习小程序的前端页面设计,Flex布局是一个非常重要的部分。和传统的布局解决方案使用 “盒状模型”,依赖display+position+float属性来控制元素的排列位置不同的是,于2009年由W3C(World Wide Web Consortium,万维网联盟)提出的新的Flex布局方案,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持。在默认情况下,Flex布局是从左向右水平依次放置组件,或者是从上到下垂直依次放置组件。当一个标签的样式属性display的值设为flex时,便表示使用了Flex弹性布局方案。在本任务的实现过程中,使用到的flex样式属性见表51
。
表51常见Flex样式属性说明
属性
作用
可选值
说明
flexdirection
表示元素的排列方式
row
元素横向排列
column
元素纵向排列
justifycontent
表示元素在主轴上的排列方式。如果元素为横向排列,则主轴为水平轴
flexstart
紧挨着主轴开始处对齐
flexend
紧挨着主轴结尾处对齐
center
在主轴居中处对齐
spacebetween
元素平均分布在主轴上
spacearound
元素平均分布在主轴上,两边留有一半的间隔空间
alignitems
表示元素在侧轴上的排列方式。如果元素为横向排列,则侧轴为纵轴
stretch
默认值,元素被拉伸以适应容器
center
元素位于侧轴中心
flexstart
元素在侧轴开始处
flexend
元素在侧轴结尾处
baseline
元素位于容器内基线上
在上面任务的实现过程中,可以看到,在5_1_view.wxss文件中,container类的display属性值为Flex,表示整个页面布局采取的是flex方案; flexdirection属性值为column,表示元素整体为纵向排列; justifycontent属性值为spacebetween,表示元素平均分布在主轴(也就是纵轴)上。同时,在demotext1、demotext2和demotext3这三个类中,alignitems和justifycontent这两个属性值都被设为center,使得色块中的文本A、B、C能在色块中水平、垂直都居中显示。
在文件5_1_view.wxml中可以看到,第一个横向排列的色块组合,在标签中使用了内联样式style="flexdirection:row;",表示里面包含的三个色块采用横向排列,第二个纵向排列的三个色块组合,在标签中使用了内联样式style="flexdirection:column;",表示里面包含的三个色块采用的是纵向排列。因此,通过对元素的flex相关的属性进行设置,得到了任务要求所展示的元素排列。
除了Flex样式的相关属性设置和在3.6节组件部分提到的所有组件共有的属性外,view组件还包含的属性见
表52
。
表52view组件属性
属性名
类型
默认值
说明
最低版本
hoverclass
String
none
指定按下去的样式类。当 hoverclass="none" 时,没有效果
hoverstoppropagation
Boolean
false
指定是否阻止本节点的祖先节点出现单击态
1.5.0
hoverstarttime
Number
50
按住后多久出现单击态,单位: 毫秒
hoverstaytime
Number
400
手指松开后单击态保留时间,单位: 毫秒
表52
中的属性主要是给用户的单击操作提供视觉反馈,例如,如果要让一个view组件(以任务中的A色块为例)在被按住时背景颜色透明度发生改变,可以在view组件中编写如下代码。
然后定义类changecolor的样式为:
.change-color{
background: rgba(26, 173, 25, 0.7);
}
因此,每当该view组件(A色块)被单击时,其背景透明度就将变成0.7,可以给用户一个直观的视觉反馈效果。
5.2滚动视图组件scrollview
【任务要求】
使用滚动视图组件scrollview,使A、B、C三个色块能如图55
所示纵向滚动和横向滚动。同时监听滚动、滚动到顶部、滚动到底部的事件,在控制台观察事件输出。
图55scrollview组件任务示例
【任务分析】
本任务主要是练习scrollview组件的使用。从图55
可以看出,主要包含纵向滚动和横向滚动两部分。要想观察相关滚动事件的输出,还需要绑定滚动事件bindscroll,滚动到顶部/左边事件bindscrolltoupper,滚动到底部/右边事件bindscrolltolower。针对这些事件,需要在js文件中编写对应的处理函数,将事件详情输出在控制台中。
【任务操作】
(1) 打开示例项目,在app.json文件的pages数组中新增一项"pages/Chapter_5/5_2_scrollview/5_2_scrollview"。保存并编译项目,让开发者工具自动生成必要的目录和页面文件。
(2) 修改5_2_scrollview.json中的内容为如下代码,使页面窗口标题显示为scrollview。
{
"navigationBarTitleText": "scroll-view"
}
(3) 在5_2_scrollview.wxml文件中编写如下代码,排列好页面元素。
scroll-view
Vertical Scroll\n纵向滚动
Horizontal Scroll\n横向滚动
(4) 在5_2_scrollview.js文件中,添加对应的scroll函数,upper函数和lower函数用来处理滚动事件,滚动到顶部事件和滚动到底部事件。完成后的5_2_scrollview.js文件内容如下。和本任务相关的函数已加粗显示。
// pages/Chapter_5/5_2_scroll-view/5_2_scroll-view.js
Page({
data: {},
onLoad: function (options) {},
onReady: function () {},
onShow: function () {},
onHide: function () {},
onUnload: function () {},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {},
upper(e) {
console.log(e)
},
lower(e) {
console.log(e)
},
scroll(e) {
console.log(e)
}
})
(5) 在5_2_view.wxss文件中写入如下内容,完成对页面样式的调整。
/* pages/Chapter_5/5_2_scroll-view/5_2_scroll-view.wxss */
page {
background-color: #F8F8F8;
height: 100%;
font-size: 32rpx;
line-height: 1.6;
}
.container {
display: flex;
flex-direction: column;
min-height: 100%;
justify-content: space-between;
font-size: 32rpx;
font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
}
.page-head{
padding: 60rpx 50rpx 80rpx;
text-align: center;
}
.page-head-title{
display: inline-block;
padding: 0 40rpx 20rpx 40rpx;
font-size: 32rpx;
color: #BEBEBE;
}
.page-head-line{
margin: 0 auto;
width: 150rpx;
height: 2rpx;
background-color: #D8D8D8;
}
.page-body {
width: 100%;
flex-grow: 1;
overflow-x: hidden;
}
.page-section{
width: 100%;
margin-bottom: 60rpx;
}
.page-section-title{
font-size: 28rpx;
color: #999999;
margin-bottom: 10rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
.page-section-spacing{
margin-top: 60rpx;
box-sizing: border-box;
padding: 0 80rpx;
}
.scroll-view_H{
white-space: nowrap;
}
.scroll-view-item{
height: 300rpx;
}
.scroll-view-item_H{
display: inline-block;
width: 100%;
height: 300rpx;
}
.demo-text-1{
position: relative;
align-items: center;
justify-content: center;
background-color: #1AAD19;
color: #FFFFFF;
font-size: 36rpx;
}
.demo-text-1:before{
content: 'A';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.demo-text-2{
position: relative;
align-items: center;
justify-content: center;
background-color: #2782D7;
color: #FFFFFF;
font-size: 36rpx;
}
.demo-text-2:before{
content: 'B';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.demo-text-3{
position: relative;
align-items: center;
justify-content: center;
background-color: #F1F1F1;
color: #353535;
font-size: 36rpx;
}
.demo-text-3:before{
content: 'C';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
(6) 添加一个名叫scrollview的编译模式,将页面5_2_scrollview设置为启动页,单击“编译”按钮,就可以在左边的模拟器中看到新建的页面的效果了。在模拟器中的纵向滚动区域滚动鼠标,可以在下方控制台看到对应事件的输出结果,分别如图56
~图58
所示。
图56输出滚动到顶部事件详情
图57输出滚动事件详情
图58输出滚动到底部事件详情
【相关知识】
scrollview表示的是可滚动的视图区域。其包含的属性见表53
。
表53scrollview组件属性说明
属性名
类型
默认值
说明
scrollx
Boolean
false
允许横向滚动
scrolly
Boolean
false
允许纵向滚动
upperthreshold
Number / String
50
距顶部/左边多远时(单位: px,2.4.0起支持rpx),触发 scrolltoupper 事件
lowerthreshold
Number / String
50
距底部/右边多远时(单位: px,2.4.0起支持rpx),触发 scrolltolower 事件
scrolltop
Number / String
设置竖向滚动条位置(单位: px,2.4.0起支持rpx)
scrollleft
Number / String
设置横向滚动条位置(单位: px,2.4.0起支持rpx)
scrollintoview
String
值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素
scrollwithanimation
Boolean
false
在设置滚动条位置时使用动画过渡
enablebacktotop
Boolean
false
iOS单击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向
bindscrolltoupper
EventHandle
滚动到顶部/左边,会触发scrolltoupper事件
bindscrolltolower
EventHandle
滚动到底部/右边,会触发 scrolltolower 事件
bindscroll
EventHandle
滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
在本次任务中,第一组三个色块,通过设置标签的scrolly属性值为true,实现了色块的纵向滚动。需要注意的是,使用竖向滚动时,需要通过WXSS 设置 height,给一个固定高度。在本任务的第一个纵向滚动的scrollview中,设置了内联样式style="height: 300rpx;",固定了整个纵向滚动区域的高度为300rpx。在第二个滚动区域中,设置了标签的scrollx属性值为true,使得三个色块可以横向滚动。
在第一个纵向滚动的scrollview组件中,还对scrolltoupper事件通过设置bindscrolltoupper属性的值绑定了函数upper(),对scrolltolower事件通过设置bindscrolltolower属性的值绑定了函数lower(),对scroll事件通过设置bindscroll属性的值绑定了函数scroll()。在第二个横向滚动的scrollview组件中,同样绑定了scroll事件,并通过函数scroll()来处理。在5_2_scrollview.js文件中,upper()函数、lower()函数和scroll()函数均是将事件详情进行了直接的输出。在输出的内容中,除了事件均包含的公共内容外,其中的event.detail包含当前元素的一些位置信息。scrollLeft表示该元素显示(可见)的内容与该元素实际内容左边的距离,因此该值在第一个纵向滚动区域触发的scroll事件中为零,在第二个横向滚动区域触发的scroll事件中会随着元素的左右滚动发生变化。scrollTop表示该元素显示(可见)的内容与该元素实际内容上边的距离,因此该值在第一个纵向滚动区域触发的scroll事件中会随着元素的上下滚动而变化,在第二个横向滚动区域触发的scroll事件中为零。scrollHeight表示元素的总高度,scrollWidth表示元素的总宽度,均包括由于溢出而无法展示在网页的不可见部分。deltaX和deltaY则分别表示在横向上和纵向上元素移动的距离,纵向滚动的话,deltaX的值为零,横向滚动的话,deltaY的值为零。
使用scrollview组件除了前面提到的纵向滚动需要设置组件的固定高度外,还有以下几点需要注意的地方。
(1) 请勿在scrollview中使用textarea、map、canvas、video组件;
(2) scrollintoview的优先级高于scrolltop;
(3) 在滚动scrollview时会阻止页面回弹,所以在scrollview中滚动,是无法触发onPullDownRefresh的;
(4) 若要使用下拉刷新,请使用页面的滚动,而不是scrollview,这样也能通过单击顶部状态栏回到页面顶部。
5.3滑块视图容器swiper
【任务要求】
创建一个页面,如图59
所示排列A、B、C三个色块,通过使用swiper组件使其可以横向滑动。同时增加一个按钮,动态控制是否显示指示点。
图59swiper组件有指示点(左)和无指示点(右)示例
【任务分析】
本次任务主要是练习swiper组件的使用。除了基本的排列显示三个色块外,还增加了一个动态控制指示点显示的功能,可以通过监听按钮的单击事件,动态修改swiper的indicatordots属性值来实现。
【任务操作】
(1) 打开示例小程序项目,在app.json文件的pages数组中新增页面“pages/Chapter_5/5_3_swiper/5_3_swiper”,单击“编译”按钮,生成5_3_swiper页面所需的文件。
(2) 打开5_3_swiper.json文件,修改其中内容为如下代码,使页面窗口标题栏显示“swiper”。
{
"navigationBarTitleText": "swiper"
}
(3) 打开5_3_swiper.wxml文件,修改其中内容为如下代码,确定页面结构。
swiper
(4) 在5_3_swiper.js文件中,新增changeIndicatorDots()函数,用来响应按钮的单击事件,修改指示点的显示状态。同时在data数组中,初始化indicatorDots的值为true,即默认显示指示点。代码如下。
// pages/Chapter_5/5_3_swiper/5_3_swiper.js
Page({
data: {
indicatorDots: true
},
onLoad: function (options) {},
onReady: function () {},
onShow: function () {},
onHide: function () {},
onUnload: function () {},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {},
changeIndicatorDots() {
this.setData({
indicatorDots: !this.data.indicatorDots
})
}
})
(5) 打开5_3_swiper.wxss文件,写入如下代码,完成对页面样式的设置。
/* pages/Chapter_5/5_3_swiper/5_3_swiper.wxss */
page {
background-color: #F8F8F8;
height: 100%;
font-size: 32rpx;
line-height: 1.6;
}
.container {
display: flex;
flex-direction: column;
min-height: 100%;
justify-content: space-between;
font-size: 32rpx;
font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
}
.page-head{
padding: 60rpx 50rpx 80rpx;
text-align: center;
}
.page-head-title{
display: inline-block;
padding: 0 40rpx 20rpx 40rpx;
font-size: 32rpx;
color: #BEBEBE;
}
.page-head-line{
margin: 0 auto;
width: 150rpx;
height: 2rpx;
background-color: #D8D8D8;
}
.page-body {
width: 100%;
flex-grow: 1;
overflow-x: hidden;
}
.page-section{
width: 100%;
margin-bottom: 60rpx;
}
.page-section-title{
font-size: 28rpx;
color: #999999;
margin-bottom: 10rpx;
padding-left: 30rpx;
padding-right: 30rpx;
padding: 0;
}
.page-section-spacing{
box-sizing: border-box;
padding: 0 80rpx;
}
.swiper-item{
display: block;
height: 150px;
}
.demo-text-1{
position: relative;
align-items: center;
justify-content: center;
background-color: #1AAD19;
color: #FFFFFF;
font-size: 36rpx;
}
.demo-text-1:before{
content: 'A';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.demo-text-2{
position: relative;
align-items: center;
justify-content: center;
background-color: #2782D7;
color: #FFFFFF;
font-size: 36rpx;
}
.demo-text-2:before{
content: 'B';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.demo-text-3{
position: relative;
align-items: center;
justify-content: center;
background-color: #F1F1F1;
color: #353535;
font-size: 36rpx;
}
.demo-text-3:before{
content: 'C';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn-area {
margin-top: 20rpx;
box-sizing: border-box;
width: 100%;
padding: 0 30rpx;
}
(6) 添加一个名为swiper的编译模式,并将5_3_swiper设置为启动页面,使用新的swiper编译模式编译项目并在模拟器中预览效果。
【相关知识】
swiper组件和前面学到的scrollview组件不一样的是,swiper组件是一次滑动一项,而scrollview组件里的内容可以连续滑动。因此在我们的swiper示例页面中,除了一个标签外,里面还包含表示滑块项目的标签。
swiper组件的相关属性见表54
。
表54swiper组件属性
属性名
类型
默认值
说明
最低版本
indicatordots
Boolean
false
是否显示面板指示点
indicatorcolor
Color
rgba(0, 0, 0, .3)
指示点颜色
1.1.0
indicatoractivecolor
Color
#000000
当前选中的指示点颜色
1.1.0
autoplay
Boolean
false
是否自动切换
current
Number
0
当前所在滑块的 index
currentitemid
String
""
当前所在滑块的 itemid ,不能与 current 被同时指定
1.9.0
interval
Number
5000
自动切换时间间隔
duration
Number
500
滑动动画时长
circular
Boolean
false
是否采用衔接滑动
vertical
Boolean
false
滑动方向是否为纵向
previousmargin
String
"0px"
前边距,可用于露出前一项的一小部分,接受 px 和 rpx 值
1.9.0
nextmargin
String
"0px"
后边距,可用于露出后一项的一小部分,接受 px 和 rpx 值
1.9.0
displaymultipleitems
Number
1
同时显示的滑块数量
1.9.0
skiphiddenitemlayout
Boolean
false
是否跳过未显示的滑块布局,设为 true 可优化复杂情况下的滑动性能,但会丢失隐藏状态滑块的布局信息
1.9.0
bindchange
EventHandle
current改变时会触发 change 事件,event.detail = {current: current, source: source}
bindanimationfinish
EventHandle
动画结束时会触发animationfinish事件,event.detail 同上
1.9.0
在swiper组件中,只可以放置swiperitem组件,反之,swiperitem组件也只能放置在swiper组件中,而且其宽高会自动设置为100%。swiperitem组件的属性说明见表55
。
表55swiperitem组件属性说明
属性名
类型
默认值
说明
最 低 版 本
itemid
String
""
该 swiperitem 的标识符
1.9.0
在本例中,我们在标签里面放置了三个标签,分别表示三个色块。在标签中,swiper组件用于确定是否显示面板指示点的属性indicatordots的值绑定到了后端的indicatorDots变量上。在5_3_swiper.js文件中的data对象中,indicatorDots被赋值为true,也就是默认显示指示点。我们为按钮的单击事件绑定了处理函数changeIndicatorDots,每次单击按钮,changeIndicatorDots函数便会将当前的indicatorDots变量值取反,实现通过单击按钮切换指示点显示状态的效果。
使用swiper组件,需要注意以下几点。
(1) swiper组件里只能放置swiperitem组件,swiperitem组件也只能被放置在swiper组件中。
(2) swiper组件的change事件返回的detail里面,source字段表示导致变更的原因。source字段的可能值如下。
① autoplay: 自动播放导致swiper发生变化。
② touch: 用户滑动引起swiper发生变化。
③ "": 其他原因将用空字符串表示。
(3) 如果在bindchange的事件回调函数中使用setData改变current值,则有可能导致setData被不停地调用,因而通常情况下请在改变current值前检测source字段来判断是否是由于用户触摸引起的。
5.4可移动视图容器movableview和movablearea
【任务要求】
使用movableview组件和movablearea组件新建如图510
所示页面,分别实现滑块的横向移动,纵向移动,以及任意移动。实现按钮的单击移动到固定位置的功能,并在任意移动的滑块C中,绑定change事件,在控制台观察滑块移动事件的输出。
图510movableview组件示例
【任务分析】
本任务使用到的是可移动视图容器movableview和movablearea。movableview表示可移动的组件/视图,movablearea表示可移动的范围。在本例中,需要限制可以移动的方向,可以通过设置movableview组件的direction属性值来实现。需要实现单击按钮将滑块移动到指定位置的功能,可以通过监听按钮单击事件,动态修改movableview的x、y属性值来实现。
【任务操作】
(1) 打开示例小程序项目,在app.json文件的pages数组中新增页面“pages/Chapter_5/5_4_movableview/5_4_ movableview”,单击“编译”按钮,生成5_4_ movableview页面所需的文件。
(2) 修改5_4_movableview.json文件内容为如下代码,使页面的窗口标题显示movableview。
{
"navigationBarTitleText": "movable-view"
}
(3) 修改文件5_4_movableview.wxml的内容为如下代码,完成页面元素的布局。
movable-view
只可以横向移动
A
只可以纵向移动
B
movable-view可以在movable-area区域内任意移动
C
(4) 修改文件5_4_movableview.wxss的内容为如下代码,完成页面的样式调整。
/* pages/Chapter_5/5_4_movable-view/5_4_movable-view.wxss */
page {
background-color: #F8F8F8;
height: 100%;
font-size: 32rpx;
line-height: 1.6;
}
button{
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.container {
display: flex;
flex-direction: column;
min-height: 100%;
justify-content: space-between;
font-size: 32rpx;
font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
}
.wrap {
display: flex;
flex-direction: row;
min-height: 100%;
}
.page-head{
padding: 60rpx 50rpx 50rpx;
text-align: center;
}
.page-head-title{
display: inline-block;
padding: 0 40rpx 20rpx 40rpx;
font-size: 32rpx;
color: #BEBEBE;
}
.page-head-line{
margin: 0 auto;
width: 150rpx;
height: 2rpx;
background-color: #D8D8D8;
}
.page-body {
width: 100%;
flex-grow: 1;
overflow-x: hidden;
}
.page-section{
width: 100%;
margin-bottom: 20rpx;
}
.page-section-title{
margin-top: 50rpx;
font-size: 28rpx;
color: #999999;
margin-bottom: 10rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
.page-section-title.top {
margin-top: 0;
}
movable-view {
display: flex;
align-items: center;
justify-content: center;
height: 100rpx;
width: 100rpx;
background: #1AAD19;
color: #fff;
}
movable-area {
height: 300rpx;
width: 300rpx;
margin: 50rpx 0rpx 0 50rpx;
background-color: #ccc;
overflow: hidden;
}
.btn-area {
margin-top: 20rpx;
box-sizing: border-box;
width: 100%;
padding: 0 30rpx;
}
(5) 在5_4_movableview.js文件中,设定属性x,y的初始值为0,新增用于处理按钮单击事件的tap()函数以及处理滑块移动事件的onChange()函数。修改完成后的5_4_movableview.js文件内容如下。
// pages/Chapter_5/5_4_movable-view/5_4_movable-view.js
Page({
data: {
x: 0,
y: 0,
},
onLoad: function (options) {},
onReady: function () {},
onShow: function () {},
onHide: function () {},
onUnload: function () {},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {},
tap() {
this.setData({
x: 30,
y: 30
})
},
onChange(e) {
console.log(e.detail)
}
})
(6) 新建名为movableview的编译模式,并设置“pages/Chapter_5/5_3_swiper/5_3_swiper”为启动页面。使用movableview编译模式编译项目,观察模拟器显示效果。
(7) 使用鼠标按住并移动滑块“C”,打开控制台,可以看到onChange()函数被执行并输出如图511
所示change事件的详情。
图511onChange()函数输出结果
【相关知识】
movableview表示可移动的视图容器,从基础库1.2.0开始支持,该容器可以在页面中拖曳滑动。其属性值说明见表56
。
表56movableview组件属性说明
属性名
类型
默认值
说明
最低版本
direction
String
none
movableview的移动方向,属性值有all、vertical、horizontal、none
inertia
Boolean
false
movableview是否带有惯性
outofbounds
Boolean
false
超过可移动区域后,movableview是否还可以移动
x
Number / String
定义x轴方向的偏移,如果x的值不在可移动范围内,会自动移动到可移动范围; 改变x的值会触发动画
续表
属性名
类型
默认值
说明
最低版本
y
Number / String
定义y轴方向的偏移,如果y的值不在可移动范围内,会自动移动到可移动范围; 改变y的值会触发动画
damping
Number
20
阻尼系数,用于控制x或y改变时的动画和过界回弹的动画,值越大移动越快
friction
Number
2
摩擦系数,用于控制惯性滑动的动画,值越大摩擦力越大,滑动越快停止; 必须大于0,否则会被设置成默认值
disabled
Boolean
false
是否禁用
1.9.90
scale
Boolean
false
是否支持双指缩放,默认缩放手势生效区域是在movableview内
1.9.90
scalemin
Number
0.5
定义缩放倍数最小值
1.9.90
scalemax
Number
10
定义缩放倍数最大值
1.9.90
scalevalue
Number
1
定义缩放倍数,取值范围为0.5~10
1.9.90
animation
Boolean
true
是否使用动画
2.1.0
bindchange
EventHandle
拖动过程中触发的事件,event.detail = {x: x, y: y, source: source},其中,source表示产生移动的原因,值可为touch(拖动)、touchoutofbounds(超出移动范围)、outofbounds(超出移动范围后的回弹)、friction(惯性)和空字符串(setData)
1.9.90
bindscale
EventHandle
缩放过程中触发的事件,event.detail = {x: x, y: y, scale: scale},其中x和y字段在2.1.0之后开始支持返回
1.9.90
除了基本事件外,movableview提供了两个特殊事件,说明见表57
。
表57movableview特殊事件
类型
触 发 条 件
最 低 版 本
htouchmove
初次手指触摸后移动为横向的移动,如果catch此事件,则意味着touchmove事件也被catch
1.9.90
vtouchmove
初次手指触摸后移动为纵向的移动,如果catch此事件,则意味着touchmove事件也被catch
1.9.90
movablearea表示movableview可移动的区域。其属性说明见表58
。
表58movablearea属性说明表
属性名
类型
默认值
说明
最低版本
scalearea
Boolean
false
当里面的movableview设置为支持双指缩放时,设置此值可将缩放手势生效区域修改为整个movablearea
1.9.90
movableview组件必须被包含在movablearea组件中,并且必须是直接子节点,否则便没有移动效果。当movableview小于movablearea时,movableview的移动范围是在movablearea内; 当movableview大于movablearea时,movableview的移动范围必须包含movablearea(x轴方向和y轴方向分开考虑)。
在本例中,三个可移动区域均是movableview小于movablearea,因此带有文本的色块也就只能在限定区域内移动。滑块“A”通过设定其direction属性值为horizontal,限制了其只能横向移动; 同理,滑块“B”的direction属性值被设置为vertical,因此只能纵向滑动。滑块“C”的direction属性值为all,表示不限制滑动方向,即可以在movablearea组件区域内任意移动。同时,滑块“C”的x属性,也就是横坐标值绑定到了后端变量x上; y属性,也就是纵坐标值,绑定到了后端变量y上,并且在5_4_movableview.js文件的data对象中,将x,y初始化为0,也就是顶齐movablearea区域的左上顶点显示。按钮的单击事件处理函数tap()则通过直接将x,y的值设置为30,实现了单击移动滑块“C”到指定位置的功能。
在使用鼠标按住并拖动滑块“C”的过程中,可以看到change事件的输出(如图511
所示),e.detail包含滑块的横、纵坐标信息,还有一个source字段表示产生改变的原因。当我们使用鼠标拖动时,可以看到source的值为“touch”,而当我们单击按钮直接将其定位到坐标为(30,30)的点时,可以看到控制台的输出如图512
所示。
图512使用按钮设置位置触发change事件输出
控制台的输出展示了滑块“C”从位置(0,0)移动到(30,30)的全过程,由于篇幅限制,图512
只截取了最后的四次输出。可以看到和图511
展示的输出不同的是,图512
的source字段为空字符串,因为这里的移动,是通过tap()函数里面的setData()直接改变x,y的值实现的,因此为空字符串。
使用movableview和movablearea组件,还有以下几点注意事项。
(1) movableview必须设置width和height属性,不设置则默认为10px;
(2) movableview默认为绝对定位,top和left属性为0px;
(3) movablearea必须设置width和height属性,不设置则默认为10px。
5.5coverview组件和coverimage组件
【任务要求】
新建如图513
所示页面,使用video标签在页面上放置一个视频,视频地址为http://t.cn/RIt6r8j。在视频上面使用coverview组件和coverimage组件放置三个由图片组成的控件,从左至右分别是播放、暂停以及停止,实现对视频播放的控制。
图513coverview和coverimage任务示例
【任务分析】
本次任务主要是针对coverview和coverimage组件的应用。这两个组件都是可以覆盖在其他组件之上的。在本次任务中,涉及视频组件的使用,包括对视频的控制操作,这部分内容可以参考第8章以及第12章内容,本次任务视频控制部分将不作重点讲解。
【任务操作】
(1) 打开示例小程序项目,在app.json文件的pages数组中新增页面“pages/Chapter_5/5_5_coverview/5_5_ coverview”,单击“编译”按钮,生成5_5_ coverview页面所需的文件。
(2) 在示例小程序项目的根目录下新建一个image文件夹,用于放置图片文件。在阿里巴巴矢量图标库(http://www.iconfont.cn/)中,分别以play、pause、stop为关键字搜索图标并下载,并将下载好的图片放置到image文件夹中。完成后的小程序文件目录结构如图514
所示。
图514image文件夹
(3) 在文件5_5_coverview.json中写入如下代码,配置窗口显示为“coverview”。
{
"navigationBarTitleText": "cover-view"
}
(4) 在文件5_5_coverview.wxml中写入如下代码,完成页面元素的排布。
cover-view
(5) 在5_5_coverview.wxss文件中写入如下代码,完成页面样式的调整。
/* pages/Chapter_5/5_5_cover-view/5_5_cover-view.wxss */
page {
background-color: #F8F8F8;
height: 100%;
font-size: 32rpx;
line-height: 1.6;
}
.container {
display: flex;
flex-direction: column;
min-height: 100%;
justify-content: space-between;
font-size: 32rpx;
font-family: -apple-system-font,Helvetica Neue,Helvetica,sans-serif;
}
.page-head{
padding: 60rpx 50rpx 80rpx;
text-align: center;
}
.page-head-title{
display: inline-block;
padding: 0 40rpx 20rpx 40rpx;
font-size: 32rpx;
color: #BEBEBE;
}
.page-head-line{
margin: 0 auto;
width: 150rpx;
height: 2rpx;
background-color: #D8D8D8;
}
.page-body {
width: 100%;
flex-grow: 1;
overflow-x: hidden;
}
.page-section{
width: 100%;
margin-bottom: 20rpx;
}
.page-section-title{
margin-top: 50rpx;
font-size: 28rpx;
color: #999999;
margin-bottom: 10rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
.page-section-gap{
box-sizing: border-box;
padding: 0 30rpx;
}
.controls {
position: relative;
top: 50%;
height: 50px;
margin-top: -25px;
display: flex;
}
.play,.pause,.stop {
flex: 1;
height: 100%;
}
.img {
width: 40px;
height: 40px;
margin: 5px auto;
}
video{
width: 100%
}
(6) 在5_5_coverview.js文件中,新建play()函数、pause()函数、stop()函数实现对视频播放的控制。
// pages/Chapter_5/5_5_cover-view/5_5_cover-view.js
Page({
data: {},
onLoad: function (options) {},
onReady: function () {
this.videoCtx = wx.createVideoContext('myVideo')
},
onShow: function () {},
onHide: function () {},
onUnload: function () {},
onPullDownRefresh: function () {},
onReachBottom: function () {},
onShareAppMessage: function () {},
play() {
this.videoCtx.play()
},
pause() {
this.videoCtx.pause()
},
stop() {
this.videoCtx.stop()
}
})
(7) 新建一个名为coverview的编译模式,设置“pages/Chapter_5/5_5_coverview/5_5_coverview”为启动页面。使用coverview编译模式编译项目并在模拟器中观察页面效果。
【相关知识】
coverview和coverimage组件均是从基础库1.4.0开始支持。coverview表示覆盖在原生组件之上的文本视图,可覆盖的原生组件包括map、video、canvas、camera、liveplayer和livepusher,只支持嵌套coverview和coverimage,可在coverview中使用button。coverimage表示覆盖在原生组件之上的图片视图,可覆盖的原生组件同coverview,支持嵌套在coverview里。
coverview组件的属性说明见
表59。
表59coverview组件属性说明
属性名
类型
默认值
说明
最低版本
scrolltop
Number/String
设置顶部滚动偏移量,仅在设置了 overflowy: scroll 成为滚动元素后生效(单位为px,2.4.0起支持rpx)
2.1.0
coverimage组件的属性说明见表510。
表510coverimage组件属性说明
属性名
类型
默认值
说明
最低版本
src
String
图标路径,支持临时路径、网络地址(1.6.0起支持)、云文件ID(2.2.3起支持)。暂不支持base64格式
bindload
EventHandle
图片加载成功时触发
2.1.0
binderror
EventHandle
图片加载失败时触发
2.1.0
在本次任务中,在标签中嵌套了一个coverview组件,在这个coverview组件中,又嵌套了三个coverview组件,其中,每个coverview组件都嵌套了一个coverimage组件,用于放置三个控件图片。在三个coverview组件中,每个组件都绑定了tap事件,对应的处理函数play(),pause()和stop()实现了对视频播放的控制。
使用coverview组件和coverimage组件需要注意以下几点。
(1) 基础库2.2.4起支持touch相关事件,也可使用hoverclass设置单击态;
(2) 基础库2.1.0起支持设置scalerotate的CSS样式,包括transition动画;
(3) 基础库1.9.90起coverview支持overflow:scroll,但不支持动态更新overflow;
(4) 基础库1.9.90起最外层coverview支持position:fixed;
(5) 基础库1.9.0起支持插在view等标签下。在此之前只可嵌套在原生组件map、video、canvas和camera内,避免嵌套在其他组件内;
(6) 基础库1.6.0起支持csstransition动画,transitionproperty只支持transform(translateX,translateY)与opacity;
(7) 基础库1.6.0起支持cssopacity;
(8) 事件模型遵循冒泡模型,但不会冒泡到原生组件;
(9) 文本建议都套上coverview标签,避免排版错误;
(10) 只支持基本的定位、布局、文本样式,不支持设置单边的border、backgroundimage、shadow、overflow:visible等;
(11) 建议子节点不要溢出父节点;
(12) 默认设置的样式有: whitespace:nowrap;lineheight:1.2;display:block;
(13) 自定义组件嵌套coverview时,自定义组件的slot及其父节点暂不支持通过wx:if控制显隐,否则会导致coverview不显示。
练习题
1. 请使用表51中的justifycontent属性,通过为其设置不同的值,实现如图515所示的显示效果。
2. 请使用表51
中的alignitems属性,通过为其设置不同的值,实现如图516
所示的显示效果。
图515主轴对齐方式练习
图516侧轴对齐方式练习
3. 在页面上新增两个按钮,一个按钮实现单击一次,色块向下移动10px的功能,另一个按钮实现单击一次,滑动到下一个色块的功能(如图517
所示)。提示: 需要使用到表53
中的scrolltop和scrollintoview属性,然后为按钮设置监听单击事件,动态改变上述两个属性的值。
4. 新建如图518
所示页面,要求滑块为纵向滑动,默认显示指示点,同时实现四个按钮的相关功能。
5. 新建一个如图519
所示页面,放置A、B、C三个可移动区域和滑块。其中,区域A的movableview大于movablearea,对A色块设置渐变色便于观察movableview和movablearea的边界; 对B色块的属性值进行设置使得movableview边界可以超出movablearea边界; 对C色块绑定change事件和scale事件,新增一个按钮实现单击放大C色块的功能,并在控制台观察C色块change事件和scale事件的输出详情。
图517通过按钮控制滚动
图518swiper组件练习示例
图519movableview练习示例
6. 新建如图520
所示页面,在地图组件上覆盖A、B、C三个色块,并给色块设置一定的透明度。
图520coverview练习