前端有许多做数据可视化的图表插件,但有时候UI设计的图可能用现成的js插件无法定制或者比较麻烦(还不如自己造轮子来的快)。

下面记录下用H5 canvas设计一个仪表盘代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
<script src="tween.umd.min.js"></script>
<style>
.container {
position: absolute;
top: 40px;
left: 100px;
width: 138px;
height: 138px;
display: flex;
align-items: center;
justify-content: center;
} #bg, #ring {
position: absolute;
width: 138px;
height: 138px;
} #bg {
background-color: #fff;
} </style>
</head>
<body style="background-color: #ccc">
<div class="container">
<div id="percent" style="z-index: 100; color: #fff;">0%</div>
<canvas id="bg" width="138" height="138"></canvas>
<canvas id="ring" width="138" height="138"></canvas>
</div>
</body>
<script>
const bgCanvas = document.querySelector('#bg');
const ringCanvas = document.querySelector('#ring');
const bgCtx = bgCanvas.getContext('2d');
const ctx = ringCanvas.getContext('2d');
const percentEl = document.querySelector('#percent'); const pixelRatio = window.devicePixelRatio;
const BG_RING_WIDTH = 6;
const POINTER_BALL_RADIUS = 6;
const CANVAS_WIDTH = 138;
const CANVAS_HEIGHT = 138;
const INNER_CIRCLE_RADIUS = 45; if(pixelRatio > 1) {
bgCanvas.width = CANVAS_WIDTH * 2;
bgCanvas.height = CANVAS_HEIGHT * 2;
ringCanvas.width = CANVAS_WIDTH * 2;
ringCanvas.height = CANVAS_HEIGHT * 2;
bgCanvas.style.width = CANVAS_WIDTH;
bgCanvas.style.height = CANVAS_HEIGHT;
ringCanvas.style.width = CANVAS_WIDTH;
ringCanvas.style.height = CANVAS_HEIGHT;
} function createBgCircle() {
bgCtx.save();
bgCtx.beginPath();
bgCtx.arc(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, INNER_CIRCLE_RADIUS, 0, 2 * Math.PI);
let gradient = bgCtx.createLinearGradient(INNER_CIRCLE_RADIUS * 2, 0, 0, INNER_CIRCLE_RADIUS * 2);
gradient.addColorStop(0, '#E69908');
gradient.addColorStop(1, '#FDF27B');
bgCtx.fillStyle = gradient;
bgCtx.fill();
bgCtx.restore();
} function createBgRing() {
bgCtx.save();
bgCtx.beginPath();
const x = CANVAS_WIDTH / 2;
const y = r = x;
bgCtx.arc(x, y, r, 0, 2 * Math.PI, true);
bgCtx.arc(x, y, x - BG_RING_WIDTH, 0, 2 * Math.PI, false);
bgCtx.fillStyle = '#EEF5F5';
bgCtx.fill();
bgCtx.restore();
} let imageLoaded = false;
let img = null; async function createProcessRing(radian) {
const x = CANVAS_WIDTH / 2;
const y = r = x;
//裁剪扇形区域
ctx.save();
ctx.beginPath();
ctx.moveTo(x, y);
ctx.arc(x, y, r, -Math.PI/2, -Math.PI/2 + radian);
ctx.clip(); if(imageLoaded) {
ctx.drawImage(img, 0, 0, img.width, img.height);
ctx.restore();
return;
} return new Promise(resolve => {
const imgUrl = "ring.png";
img = new Image();
img.src = imgUrl;
img.onload = function() {
imageLoaded = true;
ctx.drawImage(img, 0, 0, img.width, img.height);
ctx.restore();
resolve();
}
})
} function createBallPointer(x, y) {
const cx = CANVAS_WIDTH / 2;
const cy = cx;
ctx.save();
ctx.translate(cx, cy);
ctx.beginPath();
ctx.arc(x, y, POINTER_BALL_RADIUS, 0, 2 * Math.PI);
let gradient = ctx.createLinearGradient(0, POINTER_BALL_RADIUS * 2, POINTER_BALL_RADIUS * 2, 0);
gradient.addColorStop(0, '#FF8B00');
gradient.addColorStop(1, '#F2C008');
ctx.fillStyle = gradient;
ctx.fill();
ctx.restore();
} function createAnimation(startAngle = 0, endAngle = 360, callback) {
function animate(time) {
requestAnimationFrame(animate)
TWEEN.update(time)
}
requestAnimationFrame(animate) const p = {angle: startAngle}
const tween = new TWEEN.Tween(p)
.to({angle: endAngle}, 600)
.easing(TWEEN.Easing.Quadratic.Out)
.onUpdate(() => {
let radian = Math.PI / 180 * p.angle;
let x = (CANVAS_WIDTH / 2 - BG_RING_WIDTH) * Math.cos(Math.PI/2 - radian);
let y = -(CANVAS_HEIGHT / 2 - BG_RING_WIDTH) * Math.sin(Math.PI/2 - radian);
ctx.clearRect(0, 0, ringCanvas.width, ringCanvas.height);
createProcessRing(radian);
createBallPointer(x, y);
percentEl.innerText = Math.round(p.angle / 360 * 100) + '%';
})
.start();
} async function setup() {
createBgCircle();
createBgRing();
await createProcessRing();
createBallPointer(0, -(CANVAS_WIDTH / 2 - BG_RING_WIDTH/2));
createAnimation(0, 360);
} setup(); </script>
</html>

效果:

用H5 Canvas绘制一个仪表盘笔记的更多相关文章

  1. H5 canvas绘制出现模糊的问题

    在之前做移动端小游戏幸运转盘.九宫格转盘,使用到了 canvas ,也是第一次在项目中使用 canvas 来实现. 近期测试人员反应 canvas 绘制的内容太模糊,心想着用 canvas 绘制出来的 ...

  2. 使用canvas绘制一个时钟

    周末学习canvas的一些基础功能,顺带写了一个基础的时钟.现在加工一下,做的更好看一点,先放上效果图: 谈一些自己的理解: (1).要绘制一个新的样式(不想被其他样式影响,或者影响到其他样式),那么 ...

  3. HTML5 在canvas绘制一个矩形

    笔者:本笃庆军 原文地址:http://blog.csdn.net/qingdujun/article/details/32930501 一.绘制矩形 canvas使用原点(0,0)在左上角的坐标系统 ...

  4. Canvas绘制一个大鱼喂小鱼的游戏

    Canvas是HTML5中的一部分,强大的API足以让我们绘制我们任意想绘制的东西.利用Canvas的基础学习以及JavaScript面向对象的思想绘制一个小游戏,下面是源码地址https://git ...

  5. 用canvas绘制一个简易时钟

    在见识了html5中canvas的强大,笔者准备制作一个简易时钟. 下面就是成果啦,制作之前我们先分析一下,绘制一个时钟需要做哪些准备. 一 . 1.首先这个时钟分为表盘,指针(时针,分针,秒针)和数 ...

  6. 用canvas绘制一个时钟

    实现一个时钟的绘制和时间的显示 一,首先是页面的搭建html部分以及一点点的css代码,因为css这块用的比较少,所以就没有单独出来: <!DOCTYPE html> <html l ...

  7. 使用H5 canvas画一个坦克

      具体步骤如下:   1. 首先做出绘图区,作为坦克的战场   <canvas id="floor" width="800px" height=&quo ...

  8. Canvas 绘制一个像素风电子时钟

    想法是在 Canvas 上绘制由小方块组成的数字. 第一步是实现绘制小方块的方法,先画出一个边长为 5 的 10x10 个方块,使用两个 for 循环很简单就能完成. for (let i = 0; ...

  9. 没事用html5 canvas画一个仪表盘自用,自适应的哦

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Canvas绘制图形

    1.Canvas绘制一个蓝色的矩形 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...

随机推荐

  1. win11 文件夹内关闭显示更多

    使用命令提示符 打开cmd窗口,输入  reg add HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\Inpro ...

  2. select加下拉箭头

    <div class="flex"> <label>城市</label> <div class="dealerbo"& ...

  3. Linux:find 指令的选项 +n、-n、n

    描述 find 指令查找文件时可以通过时间来锁定或缩小搜查范围.其中需要利用到文件的三个时间?:Access Time(atime).Modify Time(mtime) 和 Change Time( ...

  4. because another server process exited abnormally and possibly corrupted shared memory

    一.环境 系统平台:Linux x86-64 Red Hat Enterprise Linux 7 版本:4.1.1   二.症状 Red Hat 7.2操作系统部署HGDB 4.1.1后,日志经常出 ...

  5. ABP微服务学习系列-修复System.Text.Json不支持序列化Exception

    前面我们已经把服务都启动了,然后我们试试请求API.发现请求出现500 返回错误 System.NotSupportedException: Serialization and deserializa ...

  6. MySQL Replication(数据同步技术)

                          MySQL Replication(数据同步技术) A 到 B 完成主从复制,意思是数据同步技术 从读取主的二进制日志文件,按照日志中记录对从库进行同样的操 ...

  7. windows 服务删除或停止

    1.命令行删除 cmd 管理员模式 net start 服务名   开启服务   net stop 服务名   停止服务   sc delete 服务名      删除服务      sc confi ...

  8. SOJ1728 题解

    题意 有一个长度为 \(n\) 的数列 \(a_0,a_1,\dots,a_{n-1}\) 以及一个长度为 \(m\) 的操作序列 \((b_0,c_0),(b_1,c_1)\dots(b_{m-1} ...

  9. [WinError 10061] 由于目标计算机积极拒绝,无法连接。- EnlightenGan运行

    在测试EnlightenGan时,可视化结果保存出现问题. 原因:调用visdom可视化,需要先打开visdom python -m visdom.server

  10. fabric学习笔记7

    Fabric2.0Java SDK实践-合约交易 20201303张奕博 2023.1.18 1.创建基础工程 新建一个Maven工程,添加以下依赖 <dependency> <gr ...