小程序canvas画环形百分比进度图

组件封装

component/canvas-ring目录下

canvas-ring.js

html 复制代码
<canvas style="width:{{canvasWidth}}px;height:{{canvasWidth}}px; margin:0 auto;position:relative" type="2d" id="myCanvas">
  <view class="circle-bar" style="height:{{canvasWidth}}px;">

    <view class="title_val" style="color: {{valueColor}}; font-weight:{{f_weight}}; margin-top:{{show_tip?'10':'0'}}rpx;font-size:{{f_size}}px">
      {{value}}
      <p style="font-size: 10px;display: inline;">
        {{suffix}}
      </p>
    </view>
    <view class="title_name" style="color: {{lineColor}};">
      {{title}}
    </view>
  </view>
</canvas>
canvas-ring.json
json 复制代码
{
  "component": true,
  "usingComponents": {} 
 }
canvas-ring.wxss
css 复制代码
.circle-bar{
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  position: absolute;
  top: 0;
}
.circle-bar .title_name{
  max-height: 62rpx;
  font-size: 26rpx;
  overflow:hidden;
  text-overflow:ellipsis;
  display:-webkit-box;
  -webkit-box-orient:vertical;
  -webkit-line-clamp:2;
}
.circle-bar .title_val{
  color: #333333;
}
canvas-ring.js
javascript 复制代码
var windWidth = wx.getSystemInfoSync().windowWidth; //这里获取下设备的屏幕宽度

Component({

  /**
   * 组件的属性列表
   */

  properties: {
    //画布的宽度 默认占屏幕宽度的0.4倍
    canvasWidth: {
      type: Number,
      value: windWidth * 0.4
    },
    //线条宽度 默认10
    lineWidth: {
      type: Number,
      value: 10
    },
    //线条颜色
    lineColor: {
      type: String,
      value: "#3696FA"
    },
    //标题 默认"完成率"
    title: {
      type: String,
      value: "完成率"
    },
    //当前的值 默认45
    value: {
      type: Number,
      value: 50
    },
    //值的颜色 默认""
    valueColor: {
      type: String,
      value: "#333"
    },
    //值的字体的大小颜色 默认
    f_size: {
      type: Number,
      value: 14
    },
    f_weight: {
      type: String,
      value: "500"
    },
    //最大值 默认100
    maxValue: {
      type: Number,
      value: 100
    },
    //最小值 默认0
    minValue: {
      type: Number,
      value: 0
    },
    //当前值的后缀名
    suffix: {
      type: null,
      value: "%"
    },
    //从什么角度开始 0~360之间 (12点方向为0,18点方向为180,0点方向为360)
    startDegree: {
      type: Number,
      value: 0
    }
  },
  data: {
    canvasWidth: windWidth * 0.4, //默认创建的环形图宽度为屏幕宽度的40%
    show_tip: true
  },
  methods: {
    drawCanvasRing() {

      //没标题的时候去掉margin-top的值
      if (this.data.title.replace(/(^\s*)|(\s*$)/g, "").length == 0) {
        this.setData({
          show_tip: false
        })
      }
      //canvas 2d
      const query = wx.createSelectorQuery().in(this);
      query.select("#myCanvas")
        .fields({
          node: true,
          size: true
        })
        .exec(this.init.bind(this))
    },
    init(res) {
      const canvas = res[0].node
      const ctx = canvas.getContext("2d");
      canvas.requestAnimationFrame(() => {})
      const dpr = wx.getSystemInfoSync().pixelRatio
      canvas.width = res[0].width * dpr
      canvas.height = res[0].height * dpr
      ctx.scale(dpr, dpr);
      // 大小值的计算
      var circle_r = this.data.canvasWidth / 2; //画布的一半,用来找中心点和半径
      var startDegree = this.data.startDegree; //从什么角度开始
      var maxValue = this.data.maxValue; //最大值
      var minValue = this.data.minValue; //最小值
      var value = this.data.value; //当前的值
      var lineColor = this.data.lineColor; //线条颜色
      var lineWidth = this.data.lineWidth; //线条宽度
      var percent = 360 * ((value - minValue) / (maxValue - minValue)); //计算结果
      //定义起始点
      ctx.translate(circle_r, circle_r);
      //灰色圆弧
      ctx.beginPath();
      ctx.strokeStyle = "#ebebeb";
      ctx.lineWidth = lineWidth;
      ctx.arc(0, 0, circle_r - 10, 0, 2 * Math.PI, true);
      ctx.stroke();
      ctx.closePath();
      //有色彩的圆弧
      ctx.beginPath();
      ctx.strokeStyle = lineColor;
      ctx.lineWidth = lineWidth;
      ctx.arc(0, 0, circle_r - 10, startDegree * Math.PI / 180 - 0.5 * Math.PI, percent * Math.PI / 180 + startDegree * Math.PI / 180 - 0.5 * Math.PI, false);
      ctx.stroke();
      ctx.closePath();
      console.log(this.data.value);
    }
  }
})

使用

父页面

canvas.js
javascript 复制代码
  /**
   * 页面的初始数据
   */
  data: {
    completePercent: 10, //圆环A的动态值
    completePercent2: 60 //圆环B的动态值
  },
javascript 复制代码
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: async function (options) {
    await tools.request('/main/mainTest', {
      id: 1,
    }, 'get').then((res) => {
      if (res.data.code == 1) {
        this.setData({
          completePercent: res.data.data.score.before,
          completePercent2: res.data.data.score.finish,
        })
      } else {
        wx.showToast({
          title: res.data.msg,
          icon: 'none',
        })
      }
    })

await    this.getRingsA();
await    this.getRingsB();
  },

方法

javascript 复制代码
  getRingsA() {
    this.canvasRing = this.selectComponent("#canringA");
    this.canvasRing.drawCanvasRing() //绘制圆环A
  },
  getRingsB() {
    this.canvasRing2 = this.selectComponent("#canringB");
    this.canvasRing2.drawCanvasRing() //绘制圆环B
  },
canvas.wxml
html 复制代码
 <canvas2d-ring type="2d" id="canringA" canvasWidth="{{120}}" f_weight="bold" value="{{completePercent}}" lineColor="#EA0000" f_size="21" lineWidth="{{10}}" title="{{'施工前'}}"></canvas2d-ring>
canvas.json
json 复制代码
{  
  "navigationStyle":"custom",
  "component": true,
  "usingComponents": {
    "canvas2d-ring": "/component/canvas-ring/canvas-ring"
  }
}
相关推荐
Muxiyale4 小时前
微信小程序备案的一些记录
微信小程序·小程序
ThreeYear_s7 小时前
基于FPGA婴儿安全监护系统(蓝牙小程序监测)
fpga开发·小程序
Mountain089 小时前
微信小程序BLE蓝牙模块断开后无法再次搜索到原来的蓝牙
微信小程序·小程序
上海云盾商务经理杨杨16 小时前
2025年小程序DDoS与CC攻击防御全指南:构建智能安全生态
安全·小程序·ddos
说私域17 小时前
数字化驱动下的智慧物流与零售创新:全流程无人仓与定制开发开源AI智能名片S2B2C商城小程序的协同实践
人工智能·小程序·开源·零售
Nueuis18 小时前
微信小程序使用腾讯云COS SDK实现用户头像上传
微信小程序·小程序·腾讯云
葱8911 天前
onenet连接微信小程序(mqtt协议)
微信小程序·小程序
筱歌儿1 天前
小程序问题(记录版)
前端·小程序
说私域1 天前
基于开源链动2+1模式AI智能名片S2B2C商城小程序的爆品力构建研究
人工智能·小程序·开源·零售