微信小程序canvas实现环形进度条



文章目录

  • 微信小程序canvas实现环形进度条
  • 前言
  • 一、微信小程序canvas
  • 1.基本使用
  • 2.注意事项
  • 二、上述示例canvas源码
  • 1.canvas.js封装
  • 2.页面使用
  • 总结



前言

最近在开发小程序项目中用到slider滑块,配合canvas实现小程序环形进度条。

样式如下:

小程序 progress自定义圆形进度条动态显示配置时间 微信小程序 环形进度条_ide



说明:slider是基础组件,比较简单,这里不做过多阐述

但是,如果想要了解如上关于
(1) slider加粗问题;
(2) slider刻度添加,和最终滑块值计算问题
(3) slider与环形进度条配合动态展示问题

可以私聊

一、微信小程序canvas

1.基本使用

(1)wxml

//创建画布
<canvas canvas-id="runCanvas" id="runCanvas" class='canvas'></canvas>

(2)js

//初始化画布
const ctx2 = wx.createCanvasContext(id);
//确定圆心
wx.createSelectorQuery().select('#'+id).boundingClientRect(function (rect) { //监听canvas的宽高
console.log(rect);
  var w = parseInt(rect.width / 2); //获取canvas宽的的一半
  var h = parseInt(rect.height / 2); //获取canvas高的一半,
}).exec();
//画图开始
run(c, w, h) {  //c是圆环进度百分比   w,h是圆心的坐标
	  let that = this;
	  var num = (2 * Math.PI / 100 * c) - 0.5 * Math.PI;
	  //圆环的绘制
	  ctx2.arc(w, h, w - 8, -0.5 * Math.PI, num); //绘制的动作
	 ctx2.setStrokeStyle("#ff5000"); //圆环线条的颜色
	  ctx2.setLineWidth("16");	//圆环的粗细
	  ctx2.setLineCap("butt");	//圆环结束断点的样式  butt为平直边缘 round为圆形线帽  square为正方形线帽
	  ctx2.stroke();
	  //开始绘制百分比数字
	  ctx2.beginPath();
	  ctx2.setFontSize(40); // 字体大小 注意不要加引号
	  ctx2.setFillStyle("#ff5000");	 // 字体颜色
	  ctx2.setTextAlign("center");	 // 字体位置
	  ctx2.setTextBaseline("middle");	 // 字体对齐方式
	  ctx2.fillText(c + "%", w, h);	 // 文字内容和文字坐标
	  ctx2.draw();
},
//实现动画
//实现动画效果其实使用定时器控制run方法一直执行。
canvasTap(start, end, time, w, h) {  //传入开始百分比和结束百分比的值,动画执行的时间,还有圆心横纵坐标
    var that = this;
    start++;
    if (start > end) {
      return false;
    }
    that.run(start, w, h); //调用run方法
    setTimeout(function () {
      that.canvasTap(start, end, time, w, h);
    }, time);
  },

2.注意事项

canvas 是原生组件,所以z-index对其无效。

canvas 绘制使用的单位都是 px 所以设置 宽高应该都是 px 。或者全部都是用自定义比例

二、上述示例canvas源码

1.canvas.js封装

小程序 progress自定义圆形进度条动态显示配置时间 微信小程序 环形进度条_Math_02

export default{ 
  data: {
    percentage: '', //百分比
    animTime: '', // 动画执行时间
  },
  options:{
    // 绘制圆形进度条方法
    run(c, w, h) {
      let that = this;
      // var num = (2 * Math.PI / 100 * c) - 0.5 * Math.PI;
      var num = (2 * Math.PI / 100 * c) - 1.2 * Math.PI;
      console.log(num,'看下num')
      // that.data.ctx2.arc(w, h, w - 8, -0.5 * Math.PI, num); //每个间隔绘制的弧度
      that.data.ctx2.arc(w, h, w - 8, -1.2 * Math.PI, num); //每个间隔绘制的弧度
      that.data.ctx2.setStrokeStyle("#169171");
      that.data.ctx2.setLineWidth("16");
      that.data.ctx2.setLineCap("butt");
      that.data.ctx2.stroke();
      that.data.ctx2.beginPath();
      that.data.ctx2.setFontSize(40); //注意不要加引号
      that.data.ctx2.setFillStyle("#ff5000");
      that.data.ctx2.setTextAlign("center");
      that.data.ctx2.setTextBaseline("middle");
      // 取出填充百分比
      // that.data.ctx2.fillText(c + "%", w, h);
      that.data.ctx2.draw();
    },
  /**
   * start 起始百分比
   * end 结束百分比
   * w,h 其实就是圆心横纵坐标
   */
  // 动画效果实现
  canvasTap(start, end, time, w, h) {
    var that = this;
    start++;
    if (start > end) {
      return false;
    }
    that.run(start, w, h);
    setTimeout(function () {
      that.canvasTap(start, end, time, w, h);
    }, time);
    // that.canvasTap(start, end, time, w, h);
  },
  /**
   * id----------------canvas画板id
   * percent-----------进度条百分比
   * time--------------画图动画执行的时间  
   */
    draw: function (id, percent, animTime) {
      var that = this;
      const ctx2 = wx.createCanvasContext(id);
      that.setData({
        ctx2:ctx2,
        percentage:percent,
        animTime: animTime
      });
      var time = that.data.animTime / that.data.percentage;
      wx.createSelectorQuery().select('#'+id).boundingClientRect(function (rect) { //监听canvas的宽高
        var w = parseInt(rect.width / 2); //获取canvas宽的的一半
        var h = parseInt(rect.height / 2); //获取canvas高的一半,
        that.canvasTap(0, that.data.percentage, time, w, h)
      }).exec();
    },
  } 
}

2.页面使用

(1) 引入

import Canvas from '../../utils/canvas.js'

(2) 解构

Page({
  ...Canvas.options,
  data: {
    ...Canvas.data,
  },

(3) 使用

onLoad: function (options) {
    this.draw('runCanvas',100,1000);
  },

总结

本文重点内容是:canvas基本使用,方法封装及页面使用;

疑问解答

(1)调用时更新传入数据页面可以重新绘制,可以,可以哦

(2)如果在电脑模拟器上效果完美,我设置的5s钟走完整个进度,但是手机(真机调试时)它需要走很久才能走完的问题;

解答:方案1,如果不是同时使用多个canvas,直接发布体验版查看即可(忽略性能为代价)

方案2,将封装的canvas.js中的定时器去掉,再尝试下就可以了

(3)关于canvas层级过高问题,请参考我的另一篇博文

canvas层级过高问题的解决方案