前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小程序实践:基础内容之progress组件,及如何自定义实现一个环形进度条?

小程序实践:基础内容之progress组件,及如何自定义实现一个环形进度条?

作者头像
LIYI
发布2020-04-01 10:57:43
4.2K0
发布2020-04-01 10:57:43
举报
文章被收录于专栏:艺述论专栏艺述论专栏

目录

代码语言:javascript
复制
1)主要属性2)示例代码与最佳实践
相关问题:
1)如何实现一个下载文件并显示动态进度条的功能?2)progress已选进度条如何设置圆角?3)已经加载完的进度条progress怎么点击某个按钮让它重新加载呢?4)能否实现一个圆环形进度条呢?5)progress 右边的进度百分比数字的颜色怎么设置呢?6)progress组件右侧的百分比文字,与左边离得太近了,可否增加一个边距?

本文8475字,阅读9分钟,实践40分钟

文 / 石桥码农

progress是进度条组件。

1)主要属性

progress组件的主要属性有:

progress进度条组件是一个很完备的组件了,不需要修改,就可以大部分场景需求。有两点需要注意:

a)前景色activeColor

默认是与小程序中success图标的颜色是相同的,都是“#09BB07”。虽然小程序框架给了开发者修改的自由,但是这个颜色并不能随便修改。程序中的设计风格要保持一致性,在其它地方,“#09BB07”这个颜色表示完成,在进度条里也应该作为前景完成色。如果想修改,所有地方都要修改。

在这张图中共有五个颜色,分别用作小程序中五类信息的颜色。同类信息保持颜色的一致性,有助于向用户提供清晰明确、主次分明的互动界面。

b)动画启动模式active-mode

这个属性默认为“backwards”,这是不合适的。一个进度条往往指示一件事情的进度,所以最好的动画启动模式是“forwards”,即每次从上次结束处开始。

在启用progress的active动画后,每走一段都是一段动画,每段动画都是基于css的动画绘制,都有时间。属性duration用于标识行走1%需要花费的时间,默认值为30毫秒。这个值越大,动画越细腻。

用于设计的标准屏幕宽度为375px,人类眼睛的动画觉察阀值是200毫秒,以默认值30毫秒走掉1%计算,200毫秒会走掉大约25px。这个值不能大了,再大的话动画看起来就不流畅,有卡顿。30毫秒可以视为是一个在体验上可被允许的最小值。但也不可设置过大,设置大了会影响性能。

2)示例代码与最佳实践

wxml:

代码语言:javascript
复制
<progress bindtap="onTapProgressBar" stroke-width="2" percent="{{percentValue}}" active-mode="forwards" active show-info="{{false}}" bindactiveend="onProgressActiveEnd"/>

将宽度设置为2,启用动画,从数据源中以变量绑定动画进度,使用“forwards”作为动画启动模式,不显示百分比数字。其它颜色等,采用默认值。

js:

代码语言:javascript
复制
onTapProgressBar(e){  let progress = this.data.percentValue  if (progress < 100){    progress += 5    this.setData({percentValue:Math.min(100, progress)})  }}

这个示例的动画效果与文首的动画相似,只是为了方便单击演示,进度条宽度不同。

在progress组件中虽然没有bindtap这个事情属性,但tap事件是所有视图组件的基础事件,所以在这里也可以绑定事情句柄。在这个示例中,码农以onTapProgressBar这个单击后触发的函数模拟网络加载的进度事件。

每单击一次,进度+5,到100时停止。每次进度值变化,都附有一个动画。动画基本是连续和细腻的。但如果加载任务小,时间短,这个动画也是一扫而过,基本是看不到的。

下面看一下相关问题:

1)如何实现一个下载文件并显示动态进度条的功能?

有人在开发者社区问到这个问题,他想实现一个下载文件并显示动态进度条的功能,但看了文档发现percent这个必须要有固定的值(类似80),但进度是一直变化的,该如何让它实现动态进度条呢?

示例代码就可以满足需求。当启用active、并将active-mode设置为”forwards”后,动画就会随下载进度动起来。

通过文件下载的总大小和已完成大小,可以实时计算出percent数值。需要注意的是,percent属性是动态绑定的,每次变化后,需要使用setData触发视图更新,不然动画是看不到的。

2)progress已选进度条如何设置圆角?

代码:

代码语言:javascript
复制
<progress border-radius="5" percent="20" show-info />

使用border-radius可以设置进度条外框的圆角大小,但是无法设置已选进度的圆角,即上面效果中绿色右端的圆角。

官方progress组件没有提供修改已选进度条圆角值的属性,有什么办法可以修改呢?

有人说,progress组件并不复杂,可以自己基于view组件实现一个。这也是一个办法,但若实现像progress那样功能完备的组件,没有看起来那么简单;况且,微信团队已经做好了一个,直接使用就是了,我们的目的是快速研发产品,没有必要在一个小组件上浪费太多精力。

小程序界面是基于浏览器内核渲染的,这也就是说,所有组件都是有它本身的css样式的。无奈微信开发者工具只开放了Wxml面板,屏蔽了Elements面板,没有办法直接查看progress组件的内部样式。

我们可以从微信开发者工具的本地源码中寻找办法。在下面这个文件中:

~/Library/Application\ Support/微信开发者工具/WeappCode/package.nw/js/vendor/dev/wx-components.css

放置的都是官方小程序组件的样式定义,其中有这样一条:

代码语言:javascript
复制
.wx-progress-inner-bar {  width: 0;  height: 100%;}

它就是progress组件内部已选div的css类样式。

知道了样式类名就好办了。在我们项目中wxss文件中,添加如下样式:

代码语言:javascript
复制
.wx-progress-inner-bar {  border-radius: 5px;}

给已选进度条加一个5px的圆角。看一下效果:

已经有圆角了。

progress本身有一个border-radius属性,将这个属性与上面样式中的border-radius设置成一样,就可以保证左右圆角一致。

这个方案在手机上测试,也有圆角效果。但它不是正规的路子,如果微信团队修改了内部样式类名,那么这个hack就不好用了。

但对于小微信团队和个人开发者来讲,无所谓了,能达到效果就好了,即使官方有变化,不能再用了,也不过是一个样式,不影响产品内容的展示。重要的是快速迭代,不在小问题上浪费太多时间。

3)已经加载完的进度条progress怎么点击某个按钮让它重新加载呢?

在这个使用示例中:

代码语言:javascript
复制
<progress bindtap="onTapProgressBar" stroke-width="2" percent="{{percentValue}}" active-mode="forwards" active show-info="{{false}}" bindactiveend="onProgressActiveEnd"/>

当进度条完成后,直接将percentValue再镒设置为100,并不能让动画重新播放。

有人设想改变两次,借助nextTick或延时定时器分别在两个渲染周期里设置:

代码语言:javascript
复制
this.setData({ percentValue: 0 });if (wx.canIUse('nextTick')) {  wx.nextTick(() => {    this.setData({ percentValue: 100 });  });} else {  setTimeout(() => {    this.setData({ percentValue: 100 });  }, 17);}

nextTick是基础2.2.3版本以上支持的,所以这位开发者用了wx.canIUse判断能不能使用这个Api。如果不能使用,则改用setTimeout设置一个延时定时器。

先将percentValue的值设置为0,过了一个渲染周期或17毫秒,再设置一次。这样就可以得到动画重新播放的效果。

其实每一次setData在底层都需要调用evaluateJavascript这个底层函数。这个函数用于逻辑层与视图层的通讯,它的执行本来就需要时间,并不是马上可以得到结果。因此,直接使用两次setData:

代码语言:javascript
复制
<button bindtap="onTapReloadBtn">重新加载</button>onTapReloadBtn(e){  this.setData({percentValue:0})  this.setData({percentValue:50})}

也可以达到同样的效果:

在这里有一个问题,读者朋友们请思考一下,为什么上面setTimeout设置的延时定时器,要使用17毫秒呢?

这是因为目前小程序1秒内最大渲染60帧,每帧渲染约平均花费16.66毫秒,这是一个渲染周期最小的时间单位,17毫秒相当于延时一个nextTick的效果。

4)能否实现一个圆环形进度条呢?

官方的progress组件只支持常规场景,从左向左显示进度。那么,如何实现一个类似于这样的环形进度条呢:

可以用Canvas绘制。

使用Component创建一个自定义组件circle-progress,在组件的wxml代码里放置一个canvas:

代码语言:javascript
复制
<view class='canvasBox'>  <view class='bigCircle'></view>  <view class='littleCircle'></view>  <canvas canvas-id="runCanvas" id="runCanvas" class='canvas'></canvas></view>

这个id为“runCanvas”的canvas将用于绘制两个圆圈,下面是灰色的圆,上面是绿色的圆。

在自定义组件中,通过一个percent的属性用于标识进度:

代码语言:javascript
复制
properties: {  percent: {    type: Number,    value: 50,    observer: function (newVal, oldVal) {      this.draw(newVal);    }  },},

observer用于监听属性变化,当进度增加时,调用draw函数绘制新增的进度条。

在draw函数及后续调用的函数中,计算出需要绘制的弧度及使用Canvas Api arc进行绘制是关键:

代码语言:javascript
复制
var num = (2 * Math.PI / 100 * c) - 0.5 * Math.PI;that.ctx2.arc(w, h, w - 8, -0.5 * Math.PI, num)

circle-progress是一个独立的组件。在使用时,先于json配置中声明对组件的引用:

代码语言:javascript
复制
{  "usingComponents": {    "circle-progress": "../circle-progress/index"  }}

“circle-progress”是声明的名称。声明后,在wxml中就可以这样使用:

代码语言:javascript
复制
<!-- 环形进度条 --><circle-progress id="progress1" percent="{{percentValue}}" /><button bindtap="drawProgress">redraw</button>

在js代码中模拟网络改变进度值:

代码语言:javascript
复制
drawProgress(){  if (this.data.percentValue >= 100){    this.setData({      percentValue:0    })  }  this.setData({    percentValue:this.data.percentValue+10  })}

运行效果就是上面问题起始处的gif图片的效果。所有源码在文未阶段源码中可以找到,位于:

miniprogram/pages/2.1/circle-progress

这个组件实现起来不复杂,但有两点值得注意:

a)当在自定义组件中使用wx.createCanvasContext(canvasId)创建画布的上下文绘制对象时,需要在第二个参数处传递this:

代码语言:javascript
复制
const ctx2 = wx.createCanvasContext(canvasId, this)

这样才是在组件中查找,不然只是在主文件中查找画布。

b)使用wx.createSelectorQuery().select(componentId)查找组件对象时,如果在自定义组件中,必须在查找前先调用一下in方法:

代码语言:javascript
复制
const query = wx.createSelectorQuery().in(this)query.select('#'+id).boundingClientRect((res)=>{  ...}).exec()

不然,这个组件是查找不到的。默认组件查询也仅是在主文件中查找,不涉及主文件中的子文件。

5)progress 右边的进度百分比数字的颜色怎么设置呢?

有两个方法,最简单直接的,是直接使用内联样式:

代码语言:javascript
复制
<progress percent="40" stroke-width="5" show-info style="color:red"/>

另一种方法,和第2个问题解决圆角的方法类似。就是在这个样式文件中:

~/Library/Application\ Support/微信开发者工具/WeappCode/package.nw/js/vendor/dev/wx-components.css

找到百比比文字的样式,然后在自己的wxss文件中将其重写:

代码语言:javascript
复制
.wx-progress-info {  color: red;}

现在所有progress组件的百分比文字都是红色了。

6)progress组件右侧的百分比文字,与左边离得太近了,可否增加一个边距?

就是感觉两者离得太近了,想优化一下,这也是社区上有人提的一个问题。

这个问题很简单,方法同问题5,直接修改样式就好了。并且这样的问题,涉及所有组件,最好是修改全局样式:

代码语言:javascript
复制
.wx-progress-info {  color: red;  margin-left: 5px;}

一处修改,所有progress组件都有效果了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 艺述论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档