uniapp,自绘仪表盘组件(基础篇)

在这里插入图片描述

一、为什么需要自绘仪表盘?

在物联网、数据监控等场景中,仪表盘是常见的数据可视化组件。uniapp的组件市场虽然有许多现成方案,但自绘组件具有以下优势:

  • 完全掌控视觉效果
  • 无依赖零冗余
  • 高性能Canvas渲染
  • 轻松适配多端

二、准备知识

  • 基础Canvas绘图API
  • uni-app的Canvas组件使用
  • 三角函数基础
  • Vue组件开发基础

三、实现基础仪表盘

1. 组件模板结构

<template>
  <view class="gauge-container">
    <canvas 
      canvas-id="gaugeCanvas"
      :style="{ width: canvasSize + 'px', height: canvasSize + 'px' }"
    ></canvas>
    <view class="value-text">{{ currentValue }}</view>
  </view>
</template>

2. 核心绘制逻辑

export default {
  props: {
    value: { type: Number, default: 0 },      // 当前值
    max: { type: Number, default: 100 },     // 最大值
    min: { type: Number, default: 0 },       // 最小值
    size: { type: Number, default: 300 }     // 画布尺寸
  },
  
  mounted() {
    this.initCanvas();
  },

  methods: {
    initCanvas() {
      this.ctx = uni.createCanvasContext('gaugeCanvas', this);
      this.drawBase();
      this.drawPointer();
    },

    // 绘制底盘
    drawBase() {
      const center = this.canvasSize / 2;
      const radius = center * 0.8;
      
      // 外圆环
      this.ctx.beginPath();
      this.ctx.arc(center, center, radius, 0.75 * Math.PI, 2.25 * Math.PI);
      this.ctx.strokeStyle = '#eee';
      this.ctx.lineWidth = 8;
      this.ctx.stroke();

      // 刻度线
      const totalTicks = 20;
      for (let i = 0; i <= totalTicks; i++) {
        this.ctx.save();
        this.ctx.translate(center, center);
        const angle = 0.75 * Math.PI + (i / totalTicks) * 1.5 * Math.PI;
        this.ctx.rotate(angle);
        
        // 长刻度
        this.ctx.beginPath();
        this.ctx.moveTo(radius - 15, 0);
        this.ctx.lineTo(radius, 0);
        this.ctx.strokeStyle = i % 5 === 0 ? '#333' : '#999';
        this.ctx.lineWidth = i % 5 === 0 ? 3 : 1;
        this.ctx.stroke();
        
        this.ctx.restore();
      }
    },

    // 绘制指针
    drawPointer() {
      const center = this.canvasSize / 2;
      const valueAngle = this.getCurrentAngle();
      
      this.ctx.save();
      this.ctx.translate(center, center);
      this.ctx.rotate(valueAngle);

      // 指针三角形
      this.ctx.beginPath();
      this.ctx.moveTo(-8, 0);
      this.ctx.lineTo(0, -center * 0.7);
      this.ctx.lineTo(8, 0);
      this.ctx.fillStyle = '#e64340';
      this.ctx.fill();

      // 中心圆点
      this.ctx.beginPath();
      this.ctx.arc(0, 0, 5, 0, 2 * Math.PI);
      this.ctx.fillStyle = '#333';
      this.ctx.fill();

      this.ctx.restore();
      this.ctx.draw();
    },

    getCurrentAngle() {
      const range = this.max - this.min;
      const progress = (this.value - this.min) / range;
      return 0.75 * Math.PI + progress * 1.5 * Math.PI;
    }
  }
}

3. 样式优化

.gauge-container {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}

.value-text {
  position: absolute;
  font-size: 24px;
  font-weight: bold;
  color: #333;
}

四、使用示例

<template>
  <view class="container">
    <Gauge :value="75" :max="100" size="300" />
  </view>
</template>

<script>
import Gauge from '@/components/gauge.vue'

export default {
  components: {
    Gauge
  }
}
</script>

五、核心实现原理

角度计算:将数值映射到135°~315°的扇形角度(0.75π ~ 2.25π)
坐标系变换:通过translate和rotate实现指针旋转
分层绘制:先绘制静态元素(底盘),再绘制动态元素(指针)
性能优化:使用Canvas的save/restore管理绘图状态


六、扩展方向

添加动画效果(使用requestAnimationFrame)
绘制渐变颜色区间
添加触摸交互
实现双指针仪表
添加数字标签


七、常见问题

模糊问题:确保canvas尺寸与样式尺寸一致
层级问题:数值文本需要绝对定位覆盖在canvas上
单位转换:使用uni.upx2px处理不同屏幕适配
多次绘制:在修改数据后需要手动调用draw方法

通过这个基础实现,开发者可以快速掌握uniapp中Canvas组件的使用技巧,后续可根据具体需求进行样式定制和功能扩展。这种自绘方案在H5和小程序端均可获得良好的性能表现。

你可以使用UniApp的Canvas组件来创建仪表盘。首先,你需要在uni-app项目中的pages文件夹下创建一个页面,例如Dashboard.vue。然后,在Dashboard.vue中引入Canvas组件,并在其内部编写仪表盘的逻辑。 以下是一个简单的示例代码,用于创建一个基本的仪表盘: ```html <template> <view class="dashboard"> <canvas canvas-id="dashboardCanvas" @canvaserror="canvasError"></canvas> </view> </template> <script> export default { onReady() { this.drawDashboard() }, methods: { drawDashboard() { const ctx = uni.createCanvasContext('dashboardCanvas', this) // 制背景 ctx.beginPath() ctx.arc(150, 150, 100, 0, 2 * Math.PI) ctx.setFillStyle('#f2f2f2') ctx.fill() // 制指针 ctx.beginPath() ctx.moveTo(150, 150) ctx.lineTo(150, 50) ctx.setLineWidth(5) ctx.setStrokeStyle('#ff0000') ctx.stroke() // 制刻度 for (let i = 0; i <= 10; i++) { ctx.beginPath() const startX = 150 + Math.sin(i * Math.PI / 10) * 90 const startY = 150 - Math.cos(i * Math.PI / 10) * 90 const endX = 150 + Math.sin(i * Math.PI / 10) * 80 const endY = 150 - Math.cos(i * Math.PI / 10) * 80 ctx.moveTo(startX, startY) ctx.lineTo(endX, endY) ctx.setLineWidth(2) ctx.setStrokeStyle('#000000') ctx.stroke() } ctx.draw() }, canvasError(e) { console.error('Canvas 制错误:', e.detail.errMsg) } } } </script> <style> .dashboard { width: 300px; height: 300px; } </style> ``` 你可以根据需求自定义仪表盘的样式和制逻辑。在这个示例中,我们通过Canvas的API进行背景、指针和刻度的制。最后,通过调用`ctx.draw()`方法将制内容显示在Canvas上。 当页面加载完成后,`onReady`生命周期函数会调用`drawDashboard`方法来仪表盘。如果有任何Canvas制错误,可以通过`@canvaserror`事件进行捕获和处理。 希望这个示例能帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智驾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值