用H5 Canvas绘制一个仪表盘笔记
前端有许多做数据可视化的图表插件,但有时候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绘制一个仪表盘笔记的更多相关文章
- H5 canvas绘制出现模糊的问题
在之前做移动端小游戏幸运转盘.九宫格转盘,使用到了 canvas ,也是第一次在项目中使用 canvas 来实现. 近期测试人员反应 canvas 绘制的内容太模糊,心想着用 canvas 绘制出来的 ...
- 使用canvas绘制一个时钟
周末学习canvas的一些基础功能,顺带写了一个基础的时钟.现在加工一下,做的更好看一点,先放上效果图: 谈一些自己的理解: (1).要绘制一个新的样式(不想被其他样式影响,或者影响到其他样式),那么 ...
- HTML5 在canvas绘制一个矩形
笔者:本笃庆军 原文地址:http://blog.csdn.net/qingdujun/article/details/32930501 一.绘制矩形 canvas使用原点(0,0)在左上角的坐标系统 ...
- Canvas绘制一个大鱼喂小鱼的游戏
Canvas是HTML5中的一部分,强大的API足以让我们绘制我们任意想绘制的东西.利用Canvas的基础学习以及JavaScript面向对象的思想绘制一个小游戏,下面是源码地址https://git ...
- 用canvas绘制一个简易时钟
在见识了html5中canvas的强大,笔者准备制作一个简易时钟. 下面就是成果啦,制作之前我们先分析一下,绘制一个时钟需要做哪些准备. 一 . 1.首先这个时钟分为表盘,指针(时针,分针,秒针)和数 ...
- 用canvas绘制一个时钟
实现一个时钟的绘制和时间的显示 一,首先是页面的搭建html部分以及一点点的css代码,因为css这块用的比较少,所以就没有单独出来: <!DOCTYPE html> <html l ...
- 使用H5 canvas画一个坦克
具体步骤如下: 1. 首先做出绘图区,作为坦克的战场 <canvas id="floor" width="800px" height=&quo ...
- Canvas 绘制一个像素风电子时钟
想法是在 Canvas 上绘制由小方块组成的数字. 第一步是实现绘制小方块的方法,先画出一个边长为 5 的 10x10 个方块,使用两个 for 循环很简单就能完成. for (let i = 0; ...
- 没事用html5 canvas画一个仪表盘自用,自适应的哦
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Canvas绘制图形
1.Canvas绘制一个蓝色的矩形 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...
随机推荐
- 手机访问wamp及wampserver64设置开放权限后局域网无法连接
服务器配置:在手机上WampServer电脑端网页的效果! 1.本地虚拟主机下的 Apache 目录中的bin 目录中的 config 配置文件 http.config文件使用代码编辑器. 2.将ht ...
- SpringBoot2.6.x及以上版本整合swagger文档
SpringBoot的版本更新中引入了一些新的特性,并且Swagger的版本更新也同样引入了很多新的东西,这样就造成了许多配置无法实现一一对应的情况,因此高版本的SpringBoot集成Swagger ...
- 用于双目重建中的GPU编程:julia-cuda
作者:京东科技 李大冲 一.Julia是什么 julia是2010年开始面世的语言,作为一个10后,Julia必然有前辈们没有的特点.Julia被期望塑造成原生的有C++的运行速度.python的易交 ...
- mysql查询重复的数据
---查询重复的数据 . UUID可以换成其他的需要去重的字段. 点击查看代码 select * FROM t_gzmx_reptile_receive_incre WHERE id NOT IN ( ...
- go常见的坑
1. for循环中使用短变量声明初始值 案例1: type Data struct { d *int } func main() { list := make([]Data, 0) for i := ...
- video.js没有显示已播放时间、总时间?
我们在JS中设置了显示两个时间,但是没有显示. 经过查找,有的博文说或许是JS版本太高?我们没有换JS.另一篇博文给了我们启发,修改下样式就好了,我们一看,真的是样式问题 都改成block后就看到时间 ...
- Python elasticsearch 使用心得
一.配置 python == 3.6/3.8 # 更高版本的elasticsearch会出现doc_type被统一成_doc导致旧版语句报错的情况 pip install elasticsearch= ...
- Android获取获取悬浮窗一下的view办法
getwindows可以获取当前手机屏幕所有有交互功能的view getactitywindows只能获取最顶层有交互的view
- Mysql习题系列(一):基本select语句与运算符
Mysql8.0习题系列 软件下载地址 提取码:7v7u 数据下载地址 提取码:e6p9 文章目录 Mysql8.0习题系列 1. 基本select语句 1.1 题目 1.2答案 1.查询员工12个月 ...
- More exceptional c++读书笔记【附高清PDF下载】
Part1我是在读完Scott Meyers的<Effective c++>之后才读到这本书的.能够讨论特定的主题而不是将一门语言作为一个整体来看待是我理解c++的首选方式,所以Sutte ...