canvas绘制仪表盘刻度盘

embedded/2024/12/29 8:50:00/

canvas画布可以实现在网页上绘制图形的方法,比如图表、图片处理、动画、游戏等。今天我们在vue模板下用canvas实现仪表盘的绘制。

对canvas不熟悉的同学可以先了解下canvas的API文档:canvas API中文网 - Canvas API中文文档首页地图

一、创建模板,创建canvas标签

<template><canvas ref="gauge"></canvas>
</template><script>
export default {name: 'Gauge',data() {return {width:220,    // 画布的宽度height:220,   // 画布的高度progress:0.6  // 值-进度}},mounted(){this.draw()},methods:{draw(){}},
}
</script>

二、初始化画布,并绘制背景圆弧

    draw(){// 获取canvas元素和上下文let canvas = this.$refs.gaugelet ctx = canvas.getContext("2d")// 获取设备像素比,解决移动端显示锯齿、模糊等问题const dpr = window.devicePixelRatio || 1canvas.style.width = this.width + "px"canvas.style.height = this.height + "px"canvas.height = this.height * dprcanvas.width = this.width * dprctx.scale(dpr, dpr)// 清除画布--更新画布前需要清除之前的画布内容ctx.clearRect(0, 0, canvas.width, canvas.height)// 圆心位置-宽高的一半const centerX = this.width / 2const centerY = this.height / 2const startAngle = (3 * Math.PI) / 4   // 仪表盘的初始角度const endAngle = Math.PI / 4           // 仪表盘的结束角度const totalAngle = (3 * Math.PI) / 2   // 仪表盘的总角度// 绘制背景圆弧ctx.beginPath()ctx.arc(centerX, centerY, (this.width-20)/2, startAngle, endAngle)ctx.lineWidth = 16ctx.lineCap = 'round'ctx.strokeStyle = '#FAFAFA 'ctx.stroke()}

详解:

1、仪表盘的初始角度、结束角度、总角度根据你需要的弧形进行配置。

可以参照arc api 的此图进行理解。

角度

180

270

360

初始角度

1 * Math.PI

(3 * Math.PI) / 4

0.5 * Math.PI

结束角度

0

Math.PI / 4

-0.5 * Math.PI

总角度

1 * Math.PI

(3 * Math.PI) / 2

2 * Math.PI

2、lineCap:设置或返回线条的结束端点样式;

butt

默认。向线条的每个末端添加平直的边缘。

round

向线条的每个末端添加圆形线帽。

square

向线条的每个末端添加正方形线帽。

三、绘制上层圆弧

      // 绘制上层圆弧const endAngle1 = startAngle + (totalAngle * this.progress)ctx.save()ctx.beginPath()ctx.arc(centerX, centerY, (this.width-20)/2, startAngle, endAngle1)ctx.lineWidth = 16ctx.lineCap = 'round'var gradient = ctx.createLinearGradient(0, this.height/2*Math.sqrt(2), this.width/2*Math.sqrt(2), 0);gradient.addColorStop(0, '#DDF5EC');gradient.addColorStop(1, '#04FACF');ctx.strokeStyle = gradientctx.stroke()

详解:

1、颜色设置渐变,渐变色x轴、y轴的起点和终点。根据勾股定理计算为半径的平方根。

四、绘制刻度、刻度值

      // 绘制刻度ctx.save()// 将原点移到圆心处ctx.translate(centerX, centerY)const numTicks = 100 // 刻度数量let tickLength = 0  // 刻度长度let tickWidth = 0 // 刻度宽度const scaleRadius = (this.width-50)/2   // 刻度半径let angleStep = totalAngle / numTicksfor (let i = 0; i <= numTicks; i++) {let angle = startAngle + (i * angleStep)if (i % 10 == 0) {tickWidth = 1*2   // 长刻度线的宽是小刻度的2倍tickLength = 6*1.5   // 长刻度线的长是小刻度的1.5倍} else {tickWidth = 1tickLength = 6}ctx.beginPath();ctx.lineWidth = tickWidthctx.strokeStyle = '#cccccc'// 计算刻度起点和终点的坐标let startX = (scaleRadius - tickLength) * Math.cos(angle)let startY = (scaleRadius - tickLength) * Math.sin(angle)let endX = (scaleRadius) * Math.cos(angle)let endY = (scaleRadius) * Math.sin(angle)// 绘制刻度线段ctx.moveTo(startX, startY)ctx.lineTo(endX, endY)ctx.stroke()// 绘制刻度值文本let text = i % 10 == 0 ? i : ''let textX = (scaleRadius - 20) * Math.cos(angle)let textY = (scaleRadius - 20) * Math.sin(angle)ctx.font = "12px Arial"ctx.fillStyle = '#666666'ctx.textAlign = "center"ctx.textBaseline = "middle"ctx.fillText(text, textX, textY)}ctx.restore()

五、绘制指针

      // 绘制指针const angle = startAngle + (totalAngle * this.progress)let endX = (scaleRadius - 30) * Math.cos(angle)let endY = (scaleRadius - 30) * Math.sin(angle)ctx.save()ctx.translate(centerX, centerY)  // 将原点移到圆心处ctx.beginPath()ctx.moveTo(0, 0)ctx.lineTo(endX,endY)ctx.lineWidth = 3ctx.strokeStyle = '#F8E71C'ctx.stroke()ctx.restore()

六、绘制中心点

      // 绘制中心点ctx.save()ctx.beginPath()ctx.arc(centerX, centerY, 4, 0, 2*Math.PI)ctx.fillStyle = "#666666"ctx.fill()ctx.restore()

如有疑问,欢迎留言交流;

如有定制需求,欢迎私信沟通~


http://www.ppmy.cn/embedded/148356.html

相关文章

分布式光伏电站气象站

分布式光伏电站气象站是一种集成了光伏发电与气象观测功能的高科技设备&#xff0c;其主要功能体现在以下几个方面&#xff1a; 一、实时监测与记录气象数据 分布式光伏电站气象站能够实时监测和记录光伏电站所在区域的关键气象数据&#xff0c;包括但不限于温度、湿度、风速…

分布式链路追踪-03-Jaeger、Zipkin、skywalking 中的 span 是如何设计的?

开源项目 auto-log 自动日志输出 Jaeger、Zipkin 中的 spanId 是如何生成的&#xff1f; 在 Jaeger 和 Zipkin 这两个分布式跟踪系统中&#xff0c;Span ID 是通过不同的方法生成的。 下面分别介绍它们的生成方式&#xff1a; Jaeger 中的 Span ID 生成&#xff1a; 在 Ja…

JVM执行引擎JIT深度剖析

前端编译与后端编译 Java 程序的编译过程是分两个部分的。一个部分是从java文件编译成为class文件&#xff0c;这一部分也称为前端编译。另一个部分则是这些class文件&#xff0c;需要进入到 JVM 虚拟机&#xff0c;将这些字节码指令编译成操作系统识别的具体机器指令。这一部…

线性表实验

实验目的与要求 实验目的&#xff1a; 线性表的逻辑结构特点和线性表抽象数据类型的描述方法线性表的两类存储结构设计方法以及各自的优缺点掌握线性表的基本知识深入理解、掌握并灵活运用线性表。熟练掌握线性表的存储结构及主要运算的实现掌握栈的定义、栈的逻辑结构特性和…

Antd react上传图片格式限制

限制分辨率&#xff08;像素&#xff09; <a-upload :before-upload"beforeUpload">// 上传图片宽高比例限制const beforeUpload file > {return new Promise((resolve, reject) > {// // 图片类型限制// let isJpgOrPng file.type image/png || fil…

MFC/C++学习系列之简单记录6

MFC/C学习系列之简单记录6 前言CAboutDlg和CMFCtest1Dlg的区别MSFlexGrid的限制输入其他方式 CWndCDC总结 前言 简单的记录一下&#xff01; CAboutDlg和CMFCtest1Dlg的区别 在使用添加事件后&#xff0c;出现两者&#xff0c;并且在CAboutDlg中无法使用已经定义的控件&#x…

**Adversarial Demonstration Attacks on Large Language Models**

提出advICL&#xff0c;操控示例demonstration不改变输入&#xff0c;误导模型。发现对抗性示例增加&#xff0c;icl的鲁棒性降低。 提出Transferable advICL&#xff0c;Transferable advICL生成的对抗示例可以攻击未见过的测试输入样例。 如图&#xff0c;标准攻击:仅操纵输…

【java基础系列】实现一个简单的猜数字小游戏

主要是用的java中的键盘录入和随机数两个api&#xff0c;实现这种人机交互的小游戏&#xff0c;可以用来锻炼基础算法思维 实现效果 实现代码 package com.gaofeng.day10;import java.util.Random; import java.util.Scanner;/*** author gaofeng* date 2024-12-22 - 9:21*/ …