前言昨天,我们在微信小程序中实现了一个循环进度条。今天我们想把这个圆形的进度条做成一个组件,方便以后直接使用。按照官方文档一步步创建自定义组件。创建自定义组件。第一步是创建项目结构。打开微信开发者工具创建项目,新建目录。circle自动生成jsonwxmlwxssjs4个文件。结构如下:第二步是编写组件。写json首先需要在json文件中声明自定义组件(将component字段设置为true即可将这组文件设置为自定义组件){"component":true}写wxml和wxss的同时,是需要在wxml文件中编写组件模板,在wxss文件中添加组件样式。这里我写一下圆形进度条的模板和样式,参见微信小程序圆形进度条。需要注意的是canvas是以px为单位绘制的,所以这里我统一使用px单位;其中size是根据canvas绘制的圆环的直径,后面js会讲到。组件的wxml中可以包含一个slot节点,用于承载组件用户提供的wxml结构。注意:组件中wxss不应该使用ID选择器、属性选择器和标签名称选择器。/*components/circle/circle.wxss*/.circle_box,.circle_draw{position:relative;}.circle_bg{position:absolute;}编写js在自定义组件的js文件中,需要使用Component()来注册组件,并提供组件的属性定义、内部数据和自定义方法。组件的属性值和内部数据将用于组件wxml的渲染,这里可以从组件外部传入属性值。有关详细信息,请参阅组件构造函数。/*components/circle/circle.js*/Component({options:{multipleSlots:true//在组件定义的选项中启用多插槽支持},properties:{bg:{//属性名type:String,//Type(必填),目前接受的类型包括:String,Number,Boolean,Object,Array,null(代表任意类型)value:'bg'//属性的初始值(可选),如果不指定,则为basedonTypeselectone},draw:{type:String,value:'draw'},},data:{/*私有数据,可用于模板渲染*/size:0,/*圆框大小>=2*x(x为canvas的绘制半径)*/step:1,num:100},methods:{/**相关参数*id:canvas组件的唯一标识canvas-id*x:半径canvas绘制的圆的宽度*w:Canvas绘制圆的宽度*/drawCircleBg:function(id,x,w){//设置圆外方框的大小、宽度和高度等于圆的直径this.setData({size:2*x//更新属性和数据的方法与更新页面数据的方法类似});//使用wx.createContext获取绘图上下文ctx绘制背景环varctx=wx.createCanvasContext(id,this)ctx.setLineWidth(w/2);CTX。setStrokeStyle('#20183b');ctx.setLineCap('round')ctx.beginPath();//开始一个新的Path//设置一个原点(x,y),这里是一个半径为r的圆到当前路径的路径x=y=rctx.arc(x,x,x-w,0,2*Math.PI,错误的);ctx.stroke();//描边当前路径ctx.draw();},drawCircle:function(id,x,w,step){//使用wx.createContext获取绘图上下文context以颜色绘制进度条环varcontext=wx.createCanvasContext(id,this);//设置渐变vargradient=context.createLinearGradient(2*x,x,0);gradient.addColorStop("0","#2661DD");gradient.addColorStop("0.5","#40ED94");gradient.addColorStop("1.0","#5956CC");context.setLineWidth(w);context.setStrokeStyle(渐变);context.setLineCap('round')context.beginPath();//开始一条新路径//从0到2的step是一周context.arc(x,x,x-w,-Math.PI/2,step*Math.PI-Math.PI/2,false);context.stroke();//描边当前路径context.draw()},/*内部私有方法推荐使用下划线开头,*当自定义组件触发事件时,需要使用triggerEvent方法,指定事件名称、详细对象和事件选项*/_runEvent(){//触发自定义组件事件this.triggerEvent("runEvent")}},//生命周期函数,可以是函数,也可以是methods部分定义的方法名onReady:function(){}})至此自定义组件的循环进度条就完成了,使用在自定义组件下面,我们使用索引中的自定义组件循环进度条在json文件中进行引用声明,在使用注册的自定义组件之前,首先要在页面的json文件中进行引用声明。这个时候我们需要提供每个自定义组件的Tag名称和对应的自定义组件文件路径:{"usingComponents":{"circle":"/components/circle/circle"}}在wxml文件中使用自定义组件,这样就可以使用页面的wxml中的基本组件使用相同的自定义组件,节点名是自定义组件的标签名,节点属性是传递给组件的属性值,节点名是组件的标签名自定义组件:circle;节点属性为传递给组件的属性值:bg、draw;当自定义组件触发“runEvent”事件时,调用“_runEvent”方法。{{txt}}自定义组件的wxml节点结构与数据结合后,会插入到引用的位置。在wxss/**index.wxss**//*circleprogressbartext*/.circle_info{position:absolute;中位置的内容添加一些样式宽度:100%;左:50%;顶部:50%;转换:翻译(-50%,-50%);显示:弹性;对齐项目:居中;对齐内容:中心}.circle_dot{宽度:16rpx;高度:16rpx;边界半径:50%;背景色:#fb9126;}.circle_txt{左填充:10rpx;颜色:#fff;字体大小:36rpx;letter-spacing:2rpx;}js文件调用自定义组件中的方法在wxml中我们使用到一个数据{{txt}},我们需要在js中设置数据,然后使用selectComponent选择组件实例节点onReady//index.jsdata:{txt:"Matching..."},onReady:function(){//获取圆形组件this.circle1=this.selectComponent("#circle1");//绘制背景圆this.circle1.drawCircleBg('circle_bg1',100,8)//绘制彩色圆//this.circle1.drawCircle('circle_draw1',100,8,2);},效果如下this.circle.drawCircle('circle_draw1',100,8,0.5);this.circle.drawCircle('circle_draw1',100,8,1);这。圆圈。drawCircle('circle_draw1',100,8,2);`接下来就是写定时器方法,在定时器中每隔一段时间调用一次this.circle.drawCircle(id,x,w,step),通过改变step的值动态画圆`设置几个初始data中的values定义一个定时器方法countInterval,假设count每100毫秒递增+1,当count递增到100时,就是一个圆圈,然后改变txt的值,在onReady中清除定时器调用这个timermethoddata:{txt:"Matching...",count:0,//计数器,初始值为0maxCount:100,//画环所需的步数countTimer:null,//定时器,初始值valueisnull},countInterval:function(){//设置倒计时定时器,假设count每100毫秒增加+1,当count增加到maxCount的2倍时,正好是一个圆圈(步长从0到2一周),然后更改txt值并清除定时器this.countTimer=setInterval(()=>{if(this.data.count<=2*this.data.maxCount){//绘制色环进度文章this.circle1.drawCircle('circle_draw1',100,8,this.data.count/this.data.maxCount)this.data.count++;}else{this.setData({txt:"匹配成功"});clearInterval(this.countTimer);}},100)},onReady:function(){//获取圆形组件this.circle=this.selectComponent("#circle1");//绘制背景圆this.circle.drawCircleBg('circle_bg1',100,8)//绘制彩色圆//this.circle.drawCircle('circle_draw1',100,8,2);this.countInterval()},最终效果参考上篇文章。再用自定义组件做倒计时计数可以递增,当然可以递减这里就不细说了,直接写代码wxml">{{time}}swxss/*circlecountdown*/.circle_text{position:absolute;左:50%;顶部:50%;转换:翻译(-50%,-50%);}.circle_time{颜色:#fff;字体大小:32rpx;左填充:16rpx;}js//index.js//获取应用实例constapp=getApp()Page({data:{num:100,step:null,time:null,stepTimer:null,},stepInterval:function(){//设置倒计时varn=this.data.num/2this.stepTimer=setInterval(()=>{if(this.data.num>=0){this.data.step=this.data.num/n;//绘制彩色圆圈进度条this.circle.drawCircle('circle_draw',40,4,this.data.step)if((/(^[1-9]\d*$)/.test(this.data.num/10))){//当时间为整数秒时改变时间this.setData({time:this.data.num/10});}this.data.num--;}else{this.setData({time:0});clearInterval(this.stepTimer);}},100)},changeTime:function(){//先清除定时器clearInterval(this.stepTimer);//计数器返回到100this.setData({num:100});//重新开始倒计时this.stepInterval()//触发自定义组件事件this._runEvent()},onLoad:function(){},onReady:function(){/*Countdown*///获取圆形组件this.circle=this.selectComponent("#circle");//画背景圆//this.circle.drawCircleBg('circle_bg',40,4)//画彩色圆this.stepInterval()},_runEvent(){console.log(1111)},})如果你是对效果图感兴趣,请下载完整工程。由于版本库升级,相应的更新和bug修复(20190716)1、components/circle/circle.js文件中,wx.createCanvasContext(id)修改为:wx.createCanvasContext(id,this);2.index.js中多次调用时使用不同的变量获取圆形组件this.circle=this.selectComponent("#circle");this.circle1=this.selectComponent("#circle1");