前言

昨天在微信小程序实现了圆形进度条,今天想把这个圆形进度条做成一个组件,方便以后直接拿来用。
根据官方文档自定义组件一步一步来

创建自定义组件

第一步创建项目结构

打开微信开发者工具创建一个项目,
新建目录 components 与 pages 目录同级
在components中新建一个目录circle
在circle中新建 Component 命名为 circle 自动生成 json wxml wxss js 4个文件。
结构如下:

第二步编写组件

编写json

首先需要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可这一组文件设为自定义组件)

{"component": true
}

编写wxml和wxss

同时,还要在 wxml 文件中编写组件模版,在 wxss 文件中加入组件样式, 这里我就编写圆环进度条的 模板和样式,参见微信小程序之圆形进度条。
要注意canvas绘制的是px为单位的,所以这里我统一用px单位;其中size是根据canvas绘制的圆环的直径,后面在js中会提到。
在组件的wxml中可以包含 slot 节点,用于承载组件使用者提供的wxml结构。

<!-- components/circle/circle.wxml -->
<view class="circle_box" style="width:{{size}}px;height:{{size}}px"><canvas class="circle_bg" canvas-id="{{bg}}" style="width:{{size}}px;height:{{size}}px"></canvas> <canvas class="circle_draw" canvas-id="{{draw}}" style="width:{{size}}px;height:{{size}}px"></canvas> <slot></slot>
</view>

注意:在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。

/* components/circle/circle.wxss */
.circle_box,.circle_draw{ position: relative; }
.circle_bg{position: absolute;}

编写js

在自定义组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法。
组件的属性值和内部数据将被用于组件 wxml 的渲染,其中,属性值是可由组件外部传入的。更多细节参见 Component构造器 。

/* components/circle/circle.js */
Component({options: {multipleSlots: true // 在组件定义时的选项中启用多slot支持},properties: {bg: {            // 属性名type: String,   // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)value: 'bg'     // 属性初始值(可选),如果未指定则会根据类型选择一个},draw: {type: String,value: 'draw'},},data: { /*  私有数据,可用于模版渲染 */size: 0, /* 圆环盒子大小 size >= 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  绘制背景圆环var ctx = wx.createCanvasContext(id)ctx.setLineWidth(w / 2);ctx.setStrokeStyle('#20183b');ctx.setLineCap('round')ctx.beginPath();//开始一个新的路径//设置一个原点(x,y),半径为r的圆的路径到当前路径 此处x=y=rctx.arc(x, x, x - w, 0, 2 * Math.PI, false);ctx.stroke();//对当前路径进行描边ctx.draw();},drawCircle: function (id, x, w, step) {// 使用 wx.createContext 获取绘图上下文 context  绘制彩色进度条圆环var context = wx.createCanvasContext(id);// 设置渐变var gradient = 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(gradient);context.setLineCap('round')context.beginPath();//开始一个新的路径// step 从0到2为一周context.arc(x, x, x - w, -Math.PI / 2, step * Math.PI - Math.PI / 2, false);context.stroke();//对当前路径进行描边context.draw()},/* 内部私有方法建议以下划线开头 ,* 自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项 */_runEvent() {//触发自定义组件事件this.triggerEvent("runEvent")}},// 生命周期函数,可以为函数,或一个在methods段中定义的方法名onReady: function () {}
})

自定义组件圆形进度条到此已经完成,

使用自定义组件

下面我们在index中使用 自定义组件圆形进度条

json 文件中进行引用声明

使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:

{"usingComponents": {"circle": "/components/circle/circle"}
}

wxml 文件中使用自定义组件

这样,在页面的 wxml 中就可以像使用基础组件一样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。
节点名即自定义组件的标签名:circle;
节点属性即传递给组件的属性值:bg,draw;
当自定义组件触发“runEvent”事件时,调用“_runEvent”方法。

<!--index.wxml-->
<view class="container"> <circle id='circle1' bg='circle_bg1'    draw='circle_draw1'      bind:runEvent="_runEvent" ><!-- 这部分内容将被放置在组件 <slot> 的位置上 --><view class="circle_info" bindtap="changeTime"><view class="circle_dot"></view>  <text class='circle_txt'> {{txt}}  </text></view></circle>
</view>

自定义组件的 wxml 节点结构在与数据结合之后,将被插入到引用位置内。
在wxss给 <slot> 位置上的内容添加一些样式

/**index.wxss**/
/*圆环进度条文字*/
.circle_info{position: absolute; width: 100%;left: 50%;top: 50%; transform: translate(-50%,-50%); display: flex;  align-items: center;justify-content: center
}
.circle_dot{width:16rpx;height: 16rpx;  border-radius: 50%;background-color: #fb9126;
}
.circle_txt{padding-left: 10rpx;color: #fff;font-size: 36rpx; letter-spacing: 2rpx;
}

js 文件中调用自定义组件中的方法

在wxml中我们用到一个数据{{txt}},我们需要在js中设置一下data,然后在onReady中使用selectComponent选择组件实例节点

//index.jsdata: { txt: "正在匹配中..." },onReady: function () {// 获得circle组件this.circle = this.selectComponent("#circle1");// 绘制背景圆环this.circle.drawCircleBg('circle_bg1', 100, 8)// 绘制彩色圆环 this.circle.drawCircle('circle_draw1', 100, 8, 2);  },

效果如下

this.circle.drawCircle('circle_draw1', 100, 8, 0.5); this.circle.drawCircle('circle_draw1', 100, 8, 1); this.circle.drawCircle('circle_draw1', 100, 8, 2);

`接下来要写定时器方法了,在定时器中每隔一段时间调用一次 this.circle.drawCircle(id, x, w, step)
,通过改变step的值来动态绘制圆环`

  1. 在data中设置几个初始值
  2. 定义一个定时器方法countInterval,假设每隔100毫秒 count递增+1,当 count递增到100的时候刚好是一个圆环,然后改变txt值并且清除定时器
  3. 在 onReady 中调用这个定时器方法
  data: { txt: "正在匹配中...",count: 0,//计数器,初始值为0maxCount: 100, // 绘制一个圆环所需的步骤 countTimer: null,//定时器,初始值为null},countInterval: function () {// 设置倒计时 定时器 假设每隔100毫秒 count递增+1,当 count递增到两倍maxCount的时候刚好是一个圆环( step 从0到2为一周),然后改变txt值并且清除定时器this.countTimer = setInterval(() => {   if (this.data.count <= 2 * this.data.maxCount) {        // 绘制彩色圆环进度条this.circle.drawCircle('circle_draw1', 100, 8, this.data.count / this.data.maxCount)this.data.count++;} else {this.setData({txt: "匹配成功"});clearInterval(this.countTimer); }}, 100)},onReady: function () {// 获得circle组件this.circle = this.selectComponent("#circle1");// 绘制背景圆环this.circle.drawCircleBg('circle_bg1', 100, 8)// 绘制彩色圆环 // this.circle.drawCircle('circle_draw1', 100, 8, 2);  this.countInterval()},

最终效果

参考上一篇

再次使用自定义组件做倒计时

count可以递增,当然可以递减。这里就不在赘述,直接上代码
wxml

   <circle id='circle' bg='circle_bg'    draw='circle_draw'      bind:runEvent="_runEvent" ><view class="circle_text" bindtap="changeTime"><text class='circle_time'> {{time}} s</text></view></circle>  

wxss

/*圆环倒计时*/
.circle_text{ position: absolute;  left: 50%;top: 50%; transform: translate(-50%,-50%);
}
.circle_time{  color: #fff;font-size: 32rpx;padding-left: 16rpx;
}

js

//index.js
//获取应用实例
const app = getApp()
Page({data: { num:100,step:null,time:null,stepTimer:null,},stepInterval:function(){// 设置倒计时 定时器var n = 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});}}, 100) },changeTime:function(){// 先清除定时器clearInterval(this.stepTimer);// 计数器 还原到100this.setData({num: 100});// 重新开启倒计时this.stepInterval()// 触发自定义组件事件this._runEvent()},onLoad: function () {},onReady: function () {/*倒计时*/// 获得circle组件this.circle = this.selectComponent("#circle");// 绘制背景圆环this.circle.drawCircleBg('circle_bg', 40, 4)// 绘制彩色圆环this.stepInterval()},_runEvent() {console.log(1111) },
})

效果图

若感兴趣,请下载 完整项目

微信小程序之圆形进度条(自定义组件)相关推荐

  1. 微信小程序进度条组件自定义数字_微信小程序之圆形进度条(自定义组件)

    前言 昨天在微信小程序实现了圆形进度条,今天想把这个圆形进度条做成一个组件,方便以后直接拿来用. 根据官方文档自定义组件一步一步来 创建自定义组遇新是直朋能到件 第一步创建项遇新是直朋能到分览目结构 ...

  2. 微信小程序 环形进度条_微信小程序实现圆形进度条实例分享

    本文主要和大家分享微信小程序实现圆形进度条实例,希望能帮助到大家. 小程序中使用圆形倒计时,效果图: 思路使用2个canvas 一个是背景圆环,一个是彩色圆环. 使用setInterval 让彩色圆环 ...

  3. 微信小程序 环形进度条_微信小程序实现圆形进度条动画

    本文实例为大家分享了微信小程序动画之圆形进度条,供大家参考,具体内容如下 上图: 代码: js: //获取应用实例 var app = getApp() var interval; var varNa ...

  4. 微信小程序画布圆形进度条demo

    微信小程序开发交流qq群   173683895    承接微信小程序开发.扫码加微信. 正文: wxml <!--pages/test/test.wxml--> <canvas s ...

  5. vant 半圆仪表盘_微信小程序之圆形进度条(自定义组件)

    思路 使用2个canvas 一个是背景圆环,一个是彩色圆环. 使用setInterval 让彩色圆环逐步绘制. 在看我的文章前,必须先看 ,下面转的文章,因为本文是在它们基础上修改的. 它们的缺点为: ...

  6. Mpvue微信小程序时间消耗进度条组件的实现

    实现效果: 组件源码: 组件主要涉及时间的计算.闰年的判断,比较简单,因此注释比较少. <progress></progress>组件为微信小程序官方的进度条. <tem ...

  7. 微信小程序开发学习5(自定义组件)

    微信小程序开发学习5(自定义组件) 1.学习目标 能够知道如何自定义小程序组件 能够知道小程序组件中behaviors的作用 能够知道如何安装和配置vant-weapp组件库 能够知道如何使用MobX ...

  8. 微信小程序网悦新闻开发--自定义组件开发(六)

    目录 微信小程序网悦新闻开发--功能介绍(一) 微信小程序网悦新闻开发--小程序配置(二) 微信小程序网悦新闻开发--首页模块开发(三) 微信小程序网悦新闻开发--视频模块开发(四) 微信小程序网悦新 ...

  9. 微信小程序template模板与component自定义组件的区别和使用

    前言: 除了component,微信小程序中还有另一种组件化你的方式template模板,这两者之间的区别是,template主要是展示,方法则需要在调用的页面中定义.而component组件则有自己 ...

最新文章

  1. JAVA 游览时间最长,[蓝桥杯][算法训练]景点游览-题解(Java代码)
  2. html select显示树形菜单_HTML标签总结
  3. ThreadLocal的意义和实现
  4. k8s kubesphere安装在k8s中的基础环境准备(前提条件)
  5. 孙叫兽进阶之路之压力与绩效
  6. 数据结构之图:用图解决案例,Python代码实现——24
  7. Linux九大哲学原理,Linux/Unix设计思想(全新阐释开源哲学,Jon “maddog” Hall作序推荐)...
  8. 抖音联合九大博物馆推出“云游”活动 网友可在家看展
  9. 【SSH进阶】No result defined for action **的解决方案
  10. hadoop相关问题
  11. 距离考研还有2天,我还活着
  12. 合并出错:svn Working copy and merge source not ready for reintegration
  13. php实现标签打印,标签打印软件怎么实现批量套打标签?
  14. esp32 esp8285 wf6000OTA升级小记
  15. 如何将卫星影像(高程)导出为西安80、北京54、国家2000坐标系
  16. jsmind 线条_jsmind实例扩展(思维导图)
  17. 关于springboot自动注入出现Consider defining a bean of type 'xxx' in your configuration问题解决方案...
  18. win10触摸板手势教程
  19. Verilog 实现千兆网UDP协议 基于88E1111--板级验证--增加ARP
  20. 视频转gif如何做?三步教你视频转gif制作

热门文章

  1. 2015第36周一高效程序员的45个习惯
  2. Java集合框架List,Map,Set等全面介绍
  3. 河南省2013年对口高考 计算机类专业课试题卷答案,河南省对口高考计算机专业课模拟试卷3...
  4. datatable如何生成级联数据_UE4 C++结合DataTable批量快速创建DataAsset
  5. mysql开启function,Mysql自定義函數(function)
  6. 51单片机c语言测距,求助 关于C51单片机超声波测距 C语言程序设计 高手帮帮忙...
  7. camunda视频教程_【Camunda工作流(1)工作笔记:SpringBoot整合Camunda】
  8. netty做一个posp的网络_皑云网络——接手一个新的SEM竞价账户怎么做?
  9. quicklook不能预览office_万物皆可格!给空格键施加神奇魔法的神器软件—快速预览工具QuicklookPC软件...
  10. 输入法半角和全角的快捷转换_日语输入法究极指南