微信小程序-绘制仪表盘

参考文章

1、微信小程序Canvas自绘图表之 仪表图(表盘)
2、canvas 实现环形渐变进度条

效果展示

在这里插入图片描述

前言

完整代码可移至参考文章1,若有需要,敬请移步。在此根据需要对样式进行了些修改,在此仅记录绘制表盘的代码。

代码

function drawCircle(item, that) {
    //定义画图大小
    let width = windowWidth * 0.6;
    let height = windowWidth * 0.6;

    //获取中心坐标
    let centerPoint = {
        x: width / 2,
        y: height / 2
    }

    let ctx = wx.createCanvasContext('circle');

    ctx.save();
    ctx.translate(width / 2, height / 2);	//画布移动到中心

    let each = 7.7; //每个线之间的间距度数
    let len = 270 / each; //总共画270度 每次7.7度 需要画多少条线
    let bili = 35 / 27; //比例 每一度代表多少值,用于画值

	//最外圈放射性线条
    let line = 25; //每根线的长度
    let offset = 10; // 特殊度数的额外长度
	//最内圈放射性线条
    let smallCircleWidth = 6; //内圈线条的长度
    let offsetCircle = 15;	//内圈线条距离线底部的距离
    
	//颜色
    let astart = 77;
    let bstart = 188;
    let cstart = 27;

    let aend = 244;
    let bend = 14;
    let cend = 14;

    let aeach = (aend - astart) / len;
    let beach = (bend - bstart) / len;
    let ceach = (cend - cstart) / len;
    
    ctx.rotate(45 * Math.PI / 180);

    if(!item.curtemp){
        item.curtemp = 0;
    }
    cur = item.curtemp;

    let pre = parseInt(item.curtemp / bili / each); //计算当前温度在第几根线

    //绘制中间的圆弧
    let offsetCircleH = 5;//中间的圆弧距线底部的距离
    //圆弧半径
    let circleR = centerPoint.y - line - offset;
    ctx.beginPath();
    //画一条圆弧
    // 圆弧起始位置
    let startAngle = Math.PI * 0.5;
    // 圆弧结束位置,一个整圆(Math.PI*2)乘以比例 + 起始位置
    let endAngle = (Math.PI * 2) * (270 / 360) + startAngle;
    // 每次绘制的弧度单位,越小颜色分布越均匀,但图形较小时边缘越糙
    const unit = 0.13;
    // 根据最小弧度单位计算整个圆弧可以切成多少小份
    let division = parseInt((endAngle-startAngle)/unit,10);
    // 生成渐变色数组
    let start = startAngle;
    let end = start;
    for(let i = 0; i < division; i++){
        let color = "rgb(" + (astart + i * aeach) + "," + (bstart + i * beach) + "," + (cstart + i * ceach) + ")";
        ctx.beginPath();
        ctx.setLineCap("round");
        end = start+unit;
        ctx.setLineWidth(8);
        ctx.setStrokeStyle(color);
        ctx.arc(0,0,circleR,start,end);
        ctx.stroke();
        start+=unit;
    }
    // ctx.arc(centerPoint.x - (line + offset + offsetCircle + smallCircleWidth * 2) * 2,centerPoint.y -(line + offset + offsetCircle + smallCircleWidth * 2) * 2,circleR,(45 + 45)*Math.PI/180,(45 + 315)*Math.PI/180);
    // ctx.setLineWidth(5);
    // //线性渲染
    // var grad = ctx.createLinearGradient(centerPoint.x - (line + offset + offsetCircle + smallCircleWidth * 2) * 2,centerPoint.y -(line + offset + offsetCircle + smallCircleWidth * 2) * 2, (line + offset + offsetCircle + smallCircleWidth * 2) * 2 - centerPoint.x,centerPoint.y -(line + offset + offsetCircle + smallCircleWidth * 2) * 2);
    // for(let i = 0; i < len; i++){
    //   let color = "rgb(" + (astart + i * aeach) + "," + (bstart + i * beach) + "," + (cstart + i * ceach) + ")";
    //   grad.addColorStop(((len - i) * each) / 270,color);
    // }
    // ctx.setStrokeStyle(grad);
    // ctx.stroke();

	//循环绘制每一根线
    for (let i = 0; i < len ; i++) {
        if (i > pre) {
            ctx.setStrokeStyle("#e0e0e0");
        } else {
            ctx.setStrokeStyle("rgb(" + (astart + i * aeach) + "," + (bstart + i * beach) + "," + (cstart + i * ceach) + ")");
        }
        ctx.beginPath();
        if(i == pre){
          ctx.setLineWidth(6);
        }else{
          ctx.setLineWidth(5);
        }

        //设置外圈线条端点样式
        ctx.setLineCap("round");
        let point = {
            x: 0,
            y: centerPoint.y
        }
        let arrivePoint = {
            x: 0,
            y: point.y - line
        }
        if (i==pre){
          ctx.setStrokeStyle("#149C89");
        }
        if (i==pre) {
            point.y = centerPoint.y - 3;
        } else {
            point.y = centerPoint.y - offset;
        }
        ctx.moveTo(point.x, point.y);
        ctx.lineTo(arrivePoint.x, arrivePoint.y);
        ctx.stroke();

        ctx.globalCompositeOperation="source-over";
        if (i==pre){
          //绘制一个小圆圈
          ctx.beginPath();
          ctx.setFillStyle('#f2f2f2');
          ctx.arc(arrivePoint.x, arrivePoint.y + 2,6,0,2*Math.PI);
          ctx.fill();
        }

        //画内圈线条
        ctx.beginPath();
        ctx.setStrokeStyle("#f1f1f1");
        ctx.setLineWidth(2);
        if ( i % 5 == 0){
          ctx.setStrokeStyle("#e7e8e9");
        }
        ctx.moveTo(arrivePoint.x, arrivePoint.y - smallCircleWidth - offsetCircle - offsetCircleH);
        ctx.lineTo(arrivePoint.x, arrivePoint.y - offsetCircle - offsetCircleH);
        ctx.stroke();

        ctx.rotate(each * Math.PI / 180);
    }

    ctx.restore();

    //画中间的数值
    let value = (item.curtemp/10 + "") || "0";
    let centerFontSize = 35;
    ctx.setFontSize(centerFontSize);
    ctx.setTextAlign("center");
    ctx.setTextBaseline("middle");
    //根据数值来判断设置字体颜色
    ctx.setFillStyle("rgb(" + (astart + pre * aeach) + "," + (bstart + pre * beach) + "," + (cstart + pre * ceach) + ")");
    ctx.fillText(value, centerPoint.x, centerPoint.y);

    //画横线
    ctx.beginPath(); //创建一条路径
    ctx.setStrokeStyle("rgb(" + (astart + pre * aeach) + "," + (bstart + pre * beach) + "," + (cstart + pre * ceach) + ")");   //设置边框为红色
    ctx.setLineWidth(3);
    ctx.moveTo(centerPoint.x - 30,centerPoint.y + (centerFontSize / 2) ) //描述路径的起点为手指触摸的x轴和y轴
    ctx.lineTo(centerPoint.x + 30,centerPoint.y + (centerFontSize / 2) ) //绘制一条直线,终点坐标为手指触摸结束后的x轴和y轴
    ctx.stroke()

    //画单位
    ctx.setFontSize(15);
    ctx.setTextAlign("center");
    ctx.setTextBaseline("top");
    ctx.setFillStyle("#000");

    // let unitFontSize = 10;
    // ctx.setFontSize(unitFontSize);
    // ctx.setTextAlign("left");
    // ctx.setTextBaseline("top");
    // ctx.setFillStyle("#000");
    // ctx.fillText("mmo/L", centerPoint.x + (value.length * centerFontSize / 3.5), centerPoint.y - centerFontSize / 2);

    ctx.fillText("mmo/L", centerPoint.x, centerPoint.y + centerFontSize / 2 + 5);

    //画刻度单位
    let unitFontSize = 10;
    ctx.setTextAlign("center");
    ctx.setTextBaseline("middle");
    ctx.setFillStyle("#666");
    //刻度单位圆的半径
    let r = centerPoint.x -  line - offset - offsetCircle - smallCircleWidth * 2;

    //刻度"0"
    ctx.setFontSize(unitFontSize);
    let xy0 = {
      x:centerPoint.x - r * Math.cos(45 * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos(45 * Math.PI / 180)
    }
    ctx.fillText(0 + "", xy0.x, xy0.y) ;

    //刻度“5”
    ctx.setFontSize(unitFontSize);
    let xy1 = {
      x:centerPoint.x - r * Math.cos((45 - 5 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 5 * each) * Math.PI / 180)
    }
    ctx.fillText(5 + "", xy1.x, xy1.y);

    //刻度“10”
    ctx.setFontSize(unitFontSize);
    let xy2 = {
      x:centerPoint.x - r * Math.cos((45 - 10 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 10 * each) * Math.PI / 180)
    }
    ctx.fillText(10 + "", xy2.x, xy2.y);

    //刻度“15”
    ctx.setFontSize(unitFontSize);
    let xy3 = {
      x:centerPoint.x - r * Math.cos((45 - 15 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 15 * each) * Math.PI / 180)
    }
    ctx.fillText(15 + "", xy3.x, xy3.y);

    //刻度“20”
    ctx.setFontSize(unitFontSize);
    let xy4 = {
      x:centerPoint.x - r * Math.cos((45 - 20 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 20 * each) * Math.PI / 180)
    }
    ctx.fillText(20 + "", xy4.x, xy4.y);

    //刻度“25”
    ctx.setFontSize(unitFontSize);
    let xy5 = {
      x:centerPoint.x - r * Math.cos((45 - 25 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 25 * each) * Math.PI / 180)
    }
    ctx.fillText(25 + "", xy5.x, xy5.y);

    //刻度“30”
    ctx.setFontSize(unitFontSize);
    let xy6 = {
      x:centerPoint.x - r * Math.cos((45 - 30 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 30 * each) * Math.PI / 180)
    }
    ctx.fillText(30 + "", xy6.x, xy6.y);

    //刻度“35”
    ctx.setFontSize(unitFontSize);
    let xy7 = {
      x:centerPoint.x - r * Math.cos((45 - 35 * each) * Math.PI / 180),
      y:centerPoint.y +  r * Math.cos((45 + 35 * each) * Math.PI / 180)
    }
    ctx.fillText(35 + "", xy7.x, xy7.y);

    ctx.draw();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值