需求

实现下图所示的仪表盘的绘制。

分析

我们先来将仪表盘进行图形拆分,并定义尺寸。

我们绘制的逻辑:

  1. 绘制中心圆
  2. 绘制环外圈圆
  3. 绘制环内圈圆
  4. 绘制刻度内圈圆
  5. 绘制刻度线
  6. 绘制刻度文字
  7. 绘制指针

定义圆

var circle = {
x: canvas.width / 2,
y: canvas.height / 2,
radius: 150
};

绘制中心圆

中心圆半径是10,圆心是画布中心。

const CENTROID_RADIUS = 10;
const CENTROID_STROKE_STYLE = 'rgba(0,0,0,.5)';
const CENTROID_FILL_STYLE = 'rgba(80,190,240,.6)'; // 画仪表盘中心
function drawCentroid() {
context.beginPath();
context.save();
context.strokeStyle = CENTROID_STROKE_STYLE;
context.fillStyoe = CENTROID_FILL_STYLE;
context.arc(circle.x, circle.y, CENTROID_RADIUS, 0, 2 * Math.PI, false);
context.stroke();
context.fill();
context.restore();
}

绘制环

这里应用了剪纸效果技巧,环外圈圆顺时针绘制,环内圈圆逆时针顺时针绘制,需要注意方向。


const RING_INNER_RADIUS = 35;
const RING_OUTER_RADIUS = 55; // 绘制环外圈圆
function drawRingOuterCircle() {
context.shadowColor = 'rgba(0,0,0,.7)';
context.shadowOffsetX = 3;
context.shadowOffsetY = 3;
context.shadowBlur = 6;
context.strokeStyle = TRACKING_DIAL_STROKING_STYLE;
context.beginPath();
context.arc(circle.x, circle.y, circle.radius + RING_OUTER_RADIUS, 0, 2 * Math.PI, true);
context.stroke(); } // 绘制环外圈圆
function drawRingInnerCircle() {
context.strokeStyle = 'rgba(0,0,0,.1)';
context.arc(circle.x, circle.y, circle.radius + RING_INNER_RADIUS, 0, 2 * Math.PI, false);
context.fillStyle = 'rgba(100,140,230,.1)';
context.fill();
context.stroke();
}

绘制效果:

绘制刻度内圈圆

const TICK_WIDTH = 10;

// 绘制刻度内圆
function drawTickInnerCircle() {
context.save();
context.beginPath();
context.strokeStyle = 'rgba(0,0,0,.1)';
context.arc(circle.x, circle.y, circle.radius + RING_INNER_RADIUS - TICK_WIDTH, 0, 2 * Math.PI, false);
context.stroke();
context.restore();
}

绘制效果:

绘制刻度线

每条刻度线,其实是一个短线段,需要确定Line的起始坐标和终止坐标。

const TICK_WIDTH = 10;

// 绘制刻度
function drawTicks() {
var radius = circle.radius + RING_INNER_RADIUS;
var ANGLE_MAX = 2 * Math.PI;
// var ANGLE_DELTA = Math.PI / 64;
var ANGLE_DELTA = Math.PI / 24; var tickWidth; context.save(); for (var angle = 0, count = 0; angle < ANGLE_MAX; angle += ANGLE_DELTA, count+=15) {
drawTick(angle, radius, count);
}
context.restore();
} function drawTick(angle, radius, count) {
var tickWidth = count % 15 === 0 ? TICK_WIDTH : TICK_WIDTH / 2; context.beginPath();
context.moveTo(circle.x + (radius - tickWidth) * Math.cos(angle), circle.y + (radius - tickWidth) * Math.sin(angle));
context.lineTo(circle.x + (radius) * Math.cos(angle), circle.y + (radius) * Math.sin(angle));
context.strokeStyle = TICK_SHORT_STROKE_STYLE;
context.stroke(); }

绘制刻度值

注意刻度值是每个2个刻度线,绘制一个text。

const ANNOTATIONS_FILL_STYLE = 'rgba(0,0,230,.9)';
const ANNOTATIONS_TEXT_SIZE = 12; function drawAnnotations() {
var radius = circle.radius + RING_INNER_RADIUS;
// var deltaAngle = Math.PI /8;
var deltaAngle = Math.PI / 12;
context.save();
context.fillStyle = ANNOTATIONS_FILL_STYLE;
context.font = ANNOTATIONS_TEXT_SIZE + 'px Helvetica'; for (var angle = 0; angle < 2 * Math.PI; angle += deltaAngle) {
context.beginPath();
var degree = (angle * 180 / Math.PI).toFixed(0);
var pt = {
x: circle.x + (radius - TICK_WIDTH * 2) * Math.cos(angle),
y: circle.x - (radius - TICK_WIDTH * 2) * Math.sin(angle)
}
if (degree !== '360') {
context.fillText(degree, pt.x, pt.y);
}
} context.restore();
}

效果:

绘制指针

这里没有动画,所以给的是固定角度。


// 绘制指针
function drawCentroidGuidewire(loc) {
var angle = -Math.PI / 4;
var radius = circle.radius + RING_OUTER_RADIUS;
var endpt; if (loc.x > circle.x) {
endpt = {
x: circle.x + radius * Math.cos(angle),
y: circle.y + radius * Math.sin(angle)
};
} else {
endpt = {
x: circle.x - radius * Math.cos(angle),
y: circle.y - radius * Math.sin(angle)
};
} context.save(); context.strokeStyle = GUIDEWIRE_STROKE_STYLE;
context.fillStyle = GUIDEWIRE_FILL_STYLE; context.beginPath();
context.moveTo(circle.x, circle.y);
context.lineTo(endpt.x, endpt.y);
context.stroke(); context.beginPath();
context.strokeStyle = TICK_LONG_STROKE_STYLE;
context.arc(endpt.x, endpt.y, 5, 0, 2 * Math.PI, false);
context.fill();
context.stroke(); context.restore();
}

最后调用的时候,先绘制指针,再绘制中心点,这样可以使指针在中心点下层,好看一些。

function drawDial() {
var loc = { x: circle.x, y: circle.y }; drawCentroidGuidewire(loc);
drawCentroid();
drawRingOuterCircle();
drawRingInnerCircle();
drawTickInnerCircle();
drawTicks();
drawAnnotations();
} // Initialization
context.shadowColor = 'rgba(0,0,0,.4)';
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.shadowBlur = 4; context.textAlign = 'center';
context.textBaseline = 'middle'; drawDial();

Canvas入门08-绘制仪表盘的更多相关文章

  1. Canvas入门(1):绘制矩形、圆、直线、曲线等基本图形

    来源:http://www.ido321.com/968.html 一.Canvas的基础知识 Canvas是HTML 5中新增的元素,专门用于绘制图形.canvas元素就相当于一块“画布”,一块无色 ...

  2. Canvas入门(2):图形渐变和图像形变换

    来源:http://www.ido321.com/986.html 一.图形渐变(均在最新版Google中测试) 1.绘制线性渐变 1: // 获取canvas 的ID 2: var canvas = ...

  3. HTML5 canvas入门

    HTML5 Canvas入门 <canvas> 标签定义图形,比如图表和其他图像,您必须使用脚本来绘制图形.在画布上(Canvas)画一个红色矩形,渐变矩形,彩色矩形,和一些彩色的文字. ...

  4. canvas入门之时钟的实现

    canvas 入门之作: 三步实现一个时钟: 直接上效果:   step 1  : 背景制作首先制作从1-12的数字: var canvas = document.getElementById('ca ...

  5. canvas学习笔记(中篇) -- canvas入门教程-- 颜色/透明度/渐变色/线宽/线条样式/虚线/文本/阴影/图片/像素处理

    [中篇] -- 建议学习时间4小时  课程共(上中下)三篇 此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例, ...

  6. Canvas 入门案例

    五.  Canvas 入门案例 1.  canvas 圆形绘制 <!DOCTYPE html> <html lang="en"> <head> ...

  7. Canvas入门笔记-实现极简画笔

    今天学习了Html5 Canvas入门,已经有大神写得很详细了http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html#8 在学习过后 ...

  8. -_-#【Canvas】导出在<canvas>元素上绘制的图像

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  9. Canvas入门到高级详解(上)

    神奇的 canvas--AICODER 全栈培训 IT 培训专家 一.canvas 简介 1.1 什么是 canvas?(了解) 是 HTML5 提供的一种新标签 <canvas>< ...

随机推荐

  1. 【shell】文本匹配问题

    原文本通过TITLE分段 TITLE1 xxx yyy TITLE2 xxx yyy hello zzz hello TITLE3 xxx hello 类似于这样的,hello可能有多个,需要打印出含 ...

  2. linux的字符集转换

    命令查看编码类型 查看命令参数 查看支持的字符集 将文件转换成utf-8 的文件(经测试比较鸡肋,不好用) [root@ag-1 hh]# iconv oldboy -f us-ascii -t ut ...

  3. PHP基础教程 PHP的页面缓冲处理机制

    PHP有很多机制.函数,其实就是魔术师,重复发挥好,其实甚至是简单应用,就会出现神奇的效果.兄弟连PHP培训 这里来讲一个ob_start()函数. ob_start()函数用于打开缓冲区,比如hea ...

  4. Python连接MySQL之Python库pymysql

    连接数据库 pymysql连接数据库的方式和使用sqlite的方式基本相同: 使用connect创建连接对象 connect.cursor创建游标对象,SQL语句的执行基本都在游标上进行 cursor ...

  5. Redis实战(十七)Redis各个版本新特性

    序言 Redis1.0 Redis2.0 Redis3.0 Redis4.0 Redis5.0 资料

  6. 苹果cms如何添加播放器预加载和缓冲广告

    1,来到系统后台>>系统>>播放器参数设置  可以看到添加预加载和缓冲广告的输入框.文件格式为html 自己写一个html的网页上传到网站进行调用即可.链接前面不要加http或 ...

  7. vue 使用 axios 时 post 请求方法传参无法发送至后台

    axios 时 post 请求方法传参无法发送至后台报错如下 Response to preflight request doesn't pass access control check: No ' ...

  8. Spring Boot教程(十八)构建RESTful API

    首先,回顾并详细说明一下在快速入门中使用的@Controller.@RestController.@RequestMapping注解.如果您对Spring MVC不熟悉并且还没有尝试过快速入门案例,建 ...

  9. SQL Server 分割字符串和合并多条数据为一行

    分割字符串函数 create function f_split(@c varchar(2000),@split varchar(2)) returns @t table(col varchar(20) ...

  10. 第三周syh

    第三周作业   7-1 判断上三角矩阵 (15 分) 上三角矩阵指主对角线以下的元素都为0的矩阵:主对角线为从矩阵的左上角至右下角的连线. 本题要求编写程序,判断一个给定的方阵是否上三角矩阵. 输入格 ...