压力程度仪表盘绘制

193 阅读4分钟

背景介绍

由于产品和UI的整活,要求仪表盘要精确还原而市面上没找到现成的,所以用我初浅的canvas技术绘制了一下仪表盘(PS:讨厌造轮子,但是没合适的轮子,留一份轮子在这,万一后面还有这种需求,改改代码自己工作上还能用)

代码实现

       /**
       * 绘制仪表盘的函数
       * params: changeType - 仪表盘数值变化类型,对应相应的labels
       */
      function drawGauge(changeType = 0) {
        // 获取画布元素和绘图上下文
        const canvas = document.getElementById("gauge"); //画布为宽400,高200的canvas元素,要改宽高需要保证宽高比2:1,因为是半圆
        const ctx = canvas.getContext("2d");

        // 计算仪表盘的中心坐标和半径
        const centerX = canvas.width / 2; // 中心X坐标
        const centerY = canvas.height; // 中心Y坐标
        const radius = 150; // 仪表盘半径(没提出去,修改时需要比高小)

        // 定义仪表盘的起始和结束弧度
        const startAngle = Math.PI; // 起始弧度 (180度)
        const endAngle = 0; // 结束弧度 (0度)

        // 计算各段之间的角度步长
        const step = (startAngle - endAngle) / 5; // 将仪表盘分成5段

        // 绘制背景弧线
        ctx.beginPath(); // 开始新路径
        ctx.arc(
          centerX, // 圆心X坐标
          centerY, // 圆心Y坐标
          radius - 30, // 圆的半径 (稍微小于总半径)
          startAngle, // 起始弧度
          startAngle + step * (changeType + 0.5) // 结束弧度
        );
        ctx.lineWidth = 3; // 设置线宽
        ctx.strokeStyle = "#e0e0e0"; // 设置线条颜色 (浅灰色)
        ctx.stroke(); // 绘制弧线

        // 绘制各段
        const labels = ["无", "较小", "一般", "较大", "很大"]; // 各段的标签

        // 循环绘制每个段落
        for (let i = 0; i < labels.length; i++) {
          ctx.beginPath(); // 开始新路径
          ctx.arc(
            centerX, // 圆心X坐标
            centerY, // 圆心Y坐标
            radius, // 圆的半径 (完整半径)
            startAngle + step * i, // 各段的开始角度
            startAngle + step * (i + 1) - 0.01 // 各段的结束角度 (稍微减去0.01以保证有分割线)
          );
          ctx.lineWidth = 50; // 设置线宽
          ctx.strokeStyle = i === changeType ? "#007bff" : "#e0e0e0"; // 当前段的颜色设为蓝色,其他为灰色
          ctx.stroke(); // 绘制弧线
          ctx.save(); // 保存当前状态

          // 绘制标签
          ctx.fillStyle = i === changeType ? "#fff" : "#000"; // 当前段标签颜色为白色,其他为黑色
          ctx.font = "14px Arial"; // 设置字体大小和类型
          const labelX =
            centerX + Math.cos(startAngle + step * (i + 0.5)) * radius; // 标签X坐标
          const labelY =
            centerY + Math.sin(startAngle + step * (i + 0.5)) * radius + 5; // 标签Y坐标 (+5是为了稍微偏移)

          ctx.translate(labelX, labelY); // 移动画布原点到标签中心
          ctx.rotate(-Math.PI / 2 + step * (i + 0.5)); // 旋转画布至合适角度
          ctx.fillText(labels[i], -ctx.measureText(labels[i]).width / 2, 0); // 绘制标签文字(居中绘制)
          ctx.restore(); // 恢复到之前保存的状态
        }

        // 绘制指针
        const pointerAngle = startAngle + step * (changeType + 0.5); // 计算指针的角度
        const pointerLength = radius - 20; // 指针的长度
        ctx.beginPath(); // 开始新路径
        ctx.moveTo(centerX, centerY); // 移动到中心点
        ctx.lineTo(
          centerX + Math.cos(pointerAngle) * pointerLength, // 指针终点X坐标
          centerY + Math.sin(pointerAngle) * pointerLength // 指针终点Y坐标
        );
        ctx.lineWidth = 1; // 指针线宽
        ctx.strokeStyle = "#ff0000"; // 指针颜色 (红色)
        ctx.stroke(); // 绘制指针

        // 用白色线盖住超长的指针
        const _pointerLength = radius - 30; // 盖住的指针长度
        ctx.beginPath(); // 开始新路径
        ctx.moveTo(centerX, centerY); // 移动到中心点
        ctx.lineTo(
          centerX + Math.cos(pointerAngle) * _pointerLength, // 盖住的指针终点X坐标
          centerY + Math.sin(pointerAngle) * _pointerLength // 盖住的指针终点Y坐标
        );
        ctx.lineWidth = 10; // 线宽
        ctx.strokeStyle = "#fff"; // 线条颜色 (白色)
        ctx.stroke(); // 绘制盖住的指针

        // 绘制指针的圆点
        ctx.beginPath(); // 开始新路径
        ctx.arc(
          centerX + Math.cos(pointerAngle) * _pointerLength, // 圆点X坐标
          centerY + Math.sin(pointerAngle) * _pointerLength, // 圆点Y坐标
          2, // 圆点半径
          0, // 起始弧度
          2 * Math.PI // 结束弧度 (完整圆)
        );
        ctx.fillStyle = "#ff0000"; // 圆点颜色 (红色)
        ctx.fill(); // 填充圆点
      }

效果如下:

image.png

方法记录

方法名用法文档链接
beginPath直接调用即可,为canvas绘制新路径developer.mozilla.org/zh-CN/docs/…
arc绘制一个圆弧(圆心X轴位置, 圆心y轴位置, 半径, 开始弧度, 结束弧度, 是否为顺时针方向绘制)developer.mozilla.org/zh-CN/docs/…
stroke绘制边框图像,边框颜色使用strokeStyle设置边框宽度使用lineWidth设置,可以理解为borderdeveloper.mozilla.org/zh-CN/docs/…
fill绘制填充图形,颜色使用fillStyle设置developer.mozilla.org/zh-CN/docs/…
save能保存当次绘制路径的图像,即当次beginPath下面绘制的东西会保存一份developer.mozilla.org/zh-CN/docs/…
restore能恢复当次保存绘制路径的图developer.mozilla.org/zh-CN/docs/…
translate平移画布(画布X轴位置, 画布y轴位置)developer.mozilla.org/zh-CN/docs/…
rotate旋转画布(画布X轴位置, 画布y轴位置)developer.mozilla.org/zh-CN/docs/…
fillText绘制文本(文本内容,文本X轴位置,文本Y轴位置)developer.mozilla.org/zh-CN/docs/…
moveTo绘制线(起始点X轴位置,起始点Y轴位置)developer.mozilla.org/zh-CN/docs/…
lineTo绘制线(画布X轴位置, 画布y轴位置),不直接渲染canvas需要使用stroke()或者fill()developer.mozilla.org/zh-CN/docs/…