小程序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"
  }
}
相关推荐
计算机-秋大田6 小时前
基于微信小程序的电子竞技信息交流平台设计与实现(LW+源码+讲解)
spring boot·后端·微信小程序·小程序·课程设计
计算机徐师兄11 小时前
Java基于SSM框架的互助学习平台小程序【附源码、文档】
小程序·互助学习·互助学习平台小程序·java互助学习微信小程序·互助学习微信小程序·互助学习平台微信小程序
西农小陈12 小时前
Python-基于PyQt5,wordcloud,pillow,numpy,os,sys的智能词云生成器
开发语言·python·小程序·pycharm·numpy·pyqt·pillow
说私域14 小时前
开源AI智能名片2+1链动模式S2B2C商城小程序:重塑私域流量运营格局
人工智能·小程序·流量运营
Colinnian17 小时前
微信小程序中在一个大边框里给每个小边框均匀分配空间
微信小程序·小程序·notepad++
说私域1 天前
今日头条公域流量引流新径:开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序融合之道
人工智能·小程序
曾经的三心草1 天前
小程序-基础加强
小程序·基础加强
说私域2 天前
智能调度体系与自动驾驶技术优化运输配送效率的研究——兼论开源AI智能名片2+1链动模式S2B2C商城小程序的应用潜力
人工智能·小程序·自动驾驶
说私域2 天前
开源2+1链动模式AI智能名片S2B2C商城小程序:利用用户争强好胜心理促进分享行为的策略研究
人工智能·小程序·开源
css趣多多2 天前
认识小程序页面,小程序的宿主环境
小程序