官方文档
进度条。组件属性的长度单位默认为px,2.4.0起支持传入单位(rpx/px)。
属性
小程序所有可视的组件都可以绑定tap事件bindtap,即使没有在属性里面显示的标明。
小程序中Boolean属性如果为真则只需要写上属性名就好了,如果要设置成假,则需要写成属性名=“false”。
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
percent | number | 否 | 百分比0~100 | |
show-info | boolean | false | 否 | 在进度条右侧显示百分比 |
border-radius | number/string | 0 | 否 | 圆角大小 |
font-size | number/string | 16 | 否 | 右侧百分比字体大小 |
stroke-width | number/string | 6 | 否 | 进度条线的宽度(这是从进度条前进的方向上来看的,从表象上来看,其实就是组件的高度) |
color | string | #09BB07 | 否 | 进度条颜色(请使用activeColor) |
activeColor | string | #09BB07 | 否 | 已选择的进度条的颜色 |
backgroundColor | string | #EBEBEB | 否 | 未选择的进度条的颜色 |
active | boolean | false | 否 | 进度条从左往右的动画 |
active-mode | string | backwards | 否 | backwards: 动画从头播;forwards:动画从上次结束点接着播(实践中一般使用forwards) |
duration | number | 30 | 否 | 进度增加1%所需毫秒数 |
bindactiveend | eventhandle | 否 | 动画完成事件 |
<progress border-radius="5" percent="20" show-info />
Progress组件的border-radius属性设置的是组件外部的圆角大小,它无法设置内部已经前进的进度条圆角。
直接改变小程序Progress组件的内部样式,进行覆盖。
当然此方法是野路子,如果有一天微信团队修改了此类名,也就不能用了。
.wx-progress-inner-bar { width:0; height: 100%; } .wx-progress-inner-bar { border-radius:5px; }
有两种实现方法,但是原理都是延迟一部分操作到下一个时间片(渲染周期)再执行。
方法一,使用nextTick函数,或者在不支持nextTick的版本中使用setTimeout函数。
此处setTimeout时间设置为17ms,是由于一般手机屏幕的刷新频率是大于等于60赫兹,所以一秒60帧刷新能保证一个比较流畅的视觉效果,1000/60 = 16.6666 ms。
方法二,调用两次setData,因为每次setData在底层都需要调用evaluateJavascript这个底层函数,这个函数它用于小程序的逻辑层与视图层之间的通讯。他的执行本身就需要时间。
具体代码如下:
<view class="gap">已经加载完的进度条Progress,如何单击某个按钮让他重新加载呢?</view> <button bindtap="resetProgress">重置</button> <button bindtap="resetProgressYet">重置YET</button> <progress border-radius="5" active-mode="forwards" active show-info percent="{{percentValue}}"></progress>
Page({ /** * 页面的初始数据 */ data: { percentValue: 20, }, resetProgress() { this.setData({ percentValue: 0 }); if (wx.canIUse('nextTick')) { wx.nextTick(() => { this.setData({ percentValue: 100 }); }); } else { setTimeout(() => { this.setData({ percentValue: 0 }); }, 17) } }, resetProgressYet(){ this.setData({ percentValue: 0 }); this.setData({ percentValue: 100 }); }, })
使用Canvas创建自定义组件:原理是这样的,用css设计两个圆,一个灰色的大部外圆,和一个白色的内部小圆,然后根据percent值的变化,控制canvas进行已完成进度的绘制。
- 在自定义组件中使用wx.createCanvasContent创建画布的上下文绘制对象时,需要在第二个参数处传递this对象。这样才是在组件中查找画布。不然就会变成了在引用它的页面中查找。
- 使用wx.createSelectorQuery创建对象的select方法,以ID查找组件对象时,如果在自定义组件中,必须在查找前先调用一下他的in方法,把this对象传递进去,不然组件是查找不到的。默认组件查询也只是在主页面查找,不会去查引用组件中的子组件。
具体代码如下:
// progress/circle-progress/index.js Component({ runTimeid: 0, behaviors: [], /** * 组件的属性列表 */ properties: { percent: { type: Number, value: 50, observer: function (newVal, oldVal) { this.draw(newVal); } } }, /** * 组件的初始数据,属于私有数据,可用于模板渲染 */ data: { //百分比 percentage: '', //动画执行时间 animTime: '' }, ready() { if (this.data.percent) this.draw(this.data.percent); }, /** * 组件的方法列表 */ methods: { // 绘制圆形进度条方法 run(c,w,h){ let that = this; var num = (2 * Math.PI / 100 * c) - 0.5 * Math.PI; that.ctx2.arc(w, h, w - 8, -0.5 * Math.PI, num); that.ctx2.setStrokeStyle('#09bb07');//绿色 that.ctx2.setLineWidth('16'); that.ctx2.setLineCap('butt'); that.ctx2.stroke(); that.ctx2.beginPath(); that.ctx2.setFontSize(40);//设置字体大小,不能加引号 that.ctx2.setFillStyle('#b2b2b2');//灰色字体 that.ctx2.setTextAlign('center'); that.ctx2.setTextBaseline('middle'); that.ctx2.fillText(c+' %',w,h); that.ctx2.draw(); }, // 实现动画效果 canvasTap(start,end,time,w,h){ let that = this; start++; if(start>end){ return false; } that.run(start,w,h); that.runTimerid=setTimeout(function(){ that.canvasTap(start,end,time,w,h); },time); }, draw(percent) { const id = 'runCanvas'; const animTime = 500; if(percent>100)return if(!this.ctx2){ const ctx2=wx.createCanvasContext(id, this) this.ctx2 = ctx2 } let oldPercentValue = this.data.percentage; this.setData({ percentage:percent, animTime:animTime }); var time = this.data.animTime/(this.data.percentage-oldPercentValue); const query = wx.createSelectorQuery().in(this) query.select('#'+id).boundingClientRect((res)=>{ var w = parseInt(res.width/2); var h = parseInt(res.height/2); if(this.runTimeid) clearTimeout(this.runTimeid) this.canvasTap(oldPercentValue,percent,time,w,h) }).exec() } } })
<!-- progress/circle-progress/index.wxml --> <view class="canvasBox"> <!-- 外部灰色的圆 --> <view class="bigCircle"></view> <!-- 内部白色的圆 --> <view class="littleCircle"></view> <canvas canvas-id="runCanvas" id="runCanvas" class="canvas"></canvas> </view>
/* progress/circle-progress/index.wxss */ .canvasBox { height: 500rpx; position: relative; background-color: white; } .bigCircle { width: 420rpx; height: 420rpx; border-radius: 50%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto auto; background-color: #f2f2f2; } .littleCircle { width: 350rpx; height: 350rpx; border-radius: 50%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto auto; background-color: white; } .canvas { width: 420rpx; height: 420rpx; border-radius: 50%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto auto; z-index: 99; }
引用组件申明
{ "usingComponents": { "circle-progress": "./circle-progres/index" } }
具体使用
<view class="gap">能否设计一个环形进度条?</view> <circle-progress id="progress1" percent="{{percentValue}}" /> <button bindtap="drawProgress">绘制</button>
// progress/progress.js Page({ /** * 页面的初始数据 */ data: { percentValue: 20, }, drawProgress(){ if(this.data.percentValue>=100){ this.setData({percentValue:0}) } this.setData({percentValue:this.data.percentValue+10}) } })
有两种方法:
第一种,直接覆盖组件内部的样式,这属于全局改变。
<view class="gap">Progress组件进度的百分比数字怎么设置?</view> <progress percent="40" stroke-width="5" show-info />
.wx-progress-info{ color:red; }
第二种,使用内联样式。
<view class="gap">Progress组件进度的百分比数字怎么设置?</view> <progress percent="40" stroke-width="5" show-info style="color:red"/>
直接覆盖组件内部的样式。
<view class="gap">Progress组件右侧的百分比文字,与左边离得太近了,可否增加一个边距?</view> <progress percent="40" stroke-width="5" show-info />
.wx-progress-info{ margin-left: 5px; }