经验:

  1. save-restore-restore-restore 是不行的。用 save 保存的状态只能用一次,最后两个 restore 是回不到第一次 save 的状态的。
  2. oninput 是变了就触发,onchange 是变了且 失去焦点 才触发

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><style>canvas {background: linear-gradient(20deg, rgba(255, 152, 0, 0.5) 0, rgba(255, 87, 34, 0.9) 45%, rgba(255, 87, 34, 0.8) 50%, rgba(255, 152, 0, 0.6) 100%);}</style>
</head><body><canvas id="canvas"></canvas><!-- 要用oninput,用onchange不好 --><input type="range" value="70" oninput="handleInput()" id="inputRange"><img src="" style="display:none;" id="beautiful-icon"><img src="" style="display:none;" id="beautiful-icon-light"><script>const width = 500;const height = 300;let canvas;let beautiful_icon_base64;let beautiful_icon_light_base64;window.onload = function() {// 给图片设置src(base64)document.getElementById("beautiful-icon").setAttribute("src", beautiful_icon_base64)document.getElementById("beautiful-icon-light").setAttribute("src", beautiful_icon_light_base64)// 给画布设置宽高canvas = document.getElementById("canvas");canvas.setAttribute("width", width);canvas.setAttribute("height", height);// 画一个handleInput(60);}function handleInput() {const val = parseInt(document.getElementById("inputRange").value);draw(val);}function draw(value) {let startAngle = 17 / 16 * Math.PI, // 和数学上的保持一致endAngle = -1 / 16 * Math.PI,splitNumber = 25,diamondNumber = 10,diamondSize = 20,center = [width / 2, height / 2 + 32];var ctx = canvas.getContext('2d');ctx.save();ctx.clearRect(0, 0, width, height);ctx.translate(center[0], center[1]);// ctx.beginPath();ctx.strokeStyle = 'white';ctx.lineWidth = 5;ctx.shadowBlur = 10;ctx.shadowColor = "rgba(255, 255, 255, 0.8)";ctx.arc(0, 0, 35, 2 * Math.PI - startAngle, 2 * Math.PI - endAngle, false);ctx.stroke();// 画刻度ctx.lineWidth = 2;let r1 = 90;let r2 = 105;ctx.shadowBlur = 0;for (let i = 0; i <= splitNumber; i++) {let angle = startAngle - (startAngle - endAngle) / splitNumber * i;let startX = Math.cos(angle) * r1;let startY = -Math.sin(angle) * r1;let endX = Math.cos(angle) * r2;let endY = -Math.sin(angle) * r2;if (i <= value * splitNumber / 100) {ctx.strokeStyle = 'white';} else {ctx.strokeStyle = '#ffa96d';}ctx.beginPath();ctx.moveTo(startX, startY);ctx.lineTo(endX, endY);ctx.stroke();}// 画指针ctx.strokeStyle = '#fff';let r3 = 115;let angle = startAngle - (startAngle - endAngle) / splitNumber * value * splitNumber / 100;let startX = Math.cos(Math.PI + angle) * 12;let startY = -Math.sin(Math.PI + angle) * 12;let endX = Math.cos(angle) * r3;let endY = -Math.sin(angle) * r3;ctx.lineWidth = 3;ctx.beginPath();ctx.moveTo(startX, startY);ctx.lineTo(endX, endY);ctx.stroke();// // 画指针中心的圈圈ctx.beginPath();ctx.lineWidth = 2;ctx.fillStyle = "pink";ctx.arc(0, 0, 4, 0, 2 * Math.PI);ctx.fill();ctx.stroke();// 画钻石for (let i = 0; i <= diamondNumber; i++) {ctx.restore();// 不能连着用 restore(),没有用!ctx.save();let angle = startAngle - (startAngle - endAngle) / diamondNumber * i;let startX = Math.cos(angle) * 130;let startY = -Math.sin(angle) * 130;ctx.translate(center[0] + startX, center[1] + startY);ctx.rotate(Math.PI / 2 - angle);let scale = 50;if (i < diamondNumber * 0.5) {scale = 0.5} else if (i < diamondNumber * 0.8) {scale = i / diamondNumber} else {scale = 1;}ctx.scale(scale, scale);let img;if (i <= value * diamondNumber / 100) {img = document.getElementById('beautiful-icon');} else {img = document.getElementById('beautiful-icon-light');}if (value === 0) {img = document.getElementById('beautiful-icon-light');}ctx.drawImage(img, 0, 0, diamondSize * 2, diamondSize * 2, -diamondSize, -diamondSize, diamondSize * 2, diamondSize * 2);}ctx.restore();}</script><script>beautiful_icon_base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAUCAYAAACJfM0wAAACGklEQVQ4T52VTYiOURTHf/+NomxIPkpZsKEklK+NsCFjQdREksUwG1KancxkpdlgQZIUs0KzMNhIFjQ2ZDEppXxHImIhio7+4zx1553nfce8p5567rn3/u655/mf84jCIqIT6ABWADOBIeABMCDpl5dGxBTgALA5n4fAE2BQ0t0Kp+olInqAk+VBxft9YD/wG7gAbGqy7rCkM54bBUfEALC7WPwNeANMBxak/zPwB5id41fAd2ARMLXYu07SsCJia165mjsl6Uhxk1XARWBJ+q4BJySNZFAGny1u8RRYbXA/cDQ3DUna1njNiFgMXAZeSNpVMz8XeATMy7ntBl8B9qSjQ9LNuvxFxCxJn5rk1unsBY7nfLfB94D16Zgj6WOzza38EWElOWpbn8GngUPpmCHpa5vghcDz3NtpcHcm376Vkh63Ce4Czufe5QZbk3fSMUYRkzmgSOl7S7DS8Y2sOLN2Sro+SWj54fok9VbgUss/gR2Sbv8PPCL2AZdy7TNgg6QPZUm7nF3Wti/AMklvJ1CC1WRVVbZWknvHv5KuLCJuAVty/E7S/GbgiHCpvyzmfcvBajwGbGeDrkckLa2DR0QU/tG8luvGgWvglt9GSW5MPngNMNwKOi4VDWkpK/I1sDc729WJoC3BGZ27lgvI9gOYVkB7JLmB1VptKhoiPwicK3xu9l2SKom1B87I/RPwx3F3O1b+gppF/BdXfsvYA+llAgAAAABJRU5ErkJggg==';beautiful_icon_light_base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAUCAYAAACJfM0wAAAC0klEQVQ4T52VTUgUYRjH//+xhIIIjCiD2PHrUhCRQV8XKZtdIzskBmJEdNCZhYogvEVGJ/GSiburEUF5qvCQmbub0qHQi9JBgiB0/IhEjMKgSNqZJ2Z2V8dtV9P39M7z8Xuf9/88L0N4lhkM1MGWahDlAHaA6CX47k8eu8va+xedUGmuzZ+eW2i0wSoAVSCGxZb3IkpPSWd0MI1jemPq/iYQLd6D0nsB3m4mriRsJkh5IEBltjhFeN0Xid53fC54Qg90k1LvCV6AyDTIbQBUt1LgKwkLgl2puEkAPwApA7hlqVLKCTUUH+KUrp21yV4P9F5ROHZj6SYN2hHm8aEA+1OVPLMs625J18CY8z3TeLrMUpRQ+hYEPvzk4lFOGIFWQm4mQewtCkfPZV5zqrFqn63YjwlMqOHYhUz/ZIO/EHkYEWCP47PEPs8JQ3tC8KJjUESqfZH4y2z6zV6t2lnY3j+fzefYxnWtWSFvp/wGTcP/BkCFq2N+Yndx2+BcruTV7FOGVm6DI06MLXKHZlBrg/CaWzE2FfjCfd83Ap4J+ksTgk9urrCOpq4ZIENJsBz2heOjGwGbhtYAsNPtlCiHOGX4K23gdQq2YiLWc0BaUgJf8q38MneOTSPwApBqt2pKrS8Uf74eqLdxjr4lkXizC86Y5d+0WaN2Rl/9D9zUA5dBeZScVnxkAifVrtis90m3gGhKwb5ZlIOlofjManBTD1SA4kxVkqvwuNoRHU6e4VlmUOuD8IzbWMHn4khsby6wqQdUUMwlKFmjhqI9S9+ZiSvmWmSsOBI/kA1uGn5J29O6euNWVJx2eOEARrdb1qmCroEFxz/ZGDgmigytBv1HihWyeF6k01+x5RIUZRchT9eCrgpOjqHfeThGCvQLwNZlDdmkhqOtuXqQVYqMynUA4eUmISGChqJwLDliOdaaYCdvXNfqSTaTmFfIW76O5V9QLvBfnb8g11oJ5jAAAAAASUVORK5CYII='</script></body></html>

纯 canvas 实现漂亮的仪表盘相关推荐

  1. 纯CSS实现漂亮圆角阴影边框

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. js 纯canvas实现横纵双向关系图

    先看图: 需求如上图所示,为了不占用太多的空间,展示没有固定的方向,前期去找了很多antv/G6,echarts等插件,一个graph只有一个方向,要么从上往下,要么从左到右,都不满足需求,于是直接用 ...

  3. html漂亮的单选框,纯css3实现漂亮的单选按钮radio

    单选按钮radio是表单常见的元素,但是默认的单选按钮radio样式呆板不好看,因此通常设计人员会自己设计一个单选按钮radio,本文介绍用纯css3实现漂亮的单选按钮radio. 纯css3实现漂亮 ...

  4. css让图片显示圆角 纯CSS绘制漂亮的圆形图案效果

    css让图片显示圆角 样式: border-radius:5px 15px 20px 25px;顺序依次是上右下左 纯CSS绘制漂亮的圆形图案效果 .circle { border-radius: 5 ...

  5. 如何用纯文本生成漂亮的表格?

    巧了~不是,近期在写博客,也希望制作格式化的文本表格.这有一款在线制作漂亮的文本表格工具,纯文本输出. 如何用纯文本生成漂亮的表格? - Ayayo的回答 - 知乎 https://www.zhihu ...

  6. 不用vim-airline/lightline.vim, 如何使用纯手工制作一个漂亮的 vim 状态栏

    我将 space-vim 的状态栏单独提取成为一个插件: https://github.com/liuchengxu... , 可直接安装试用. 首先看一下最后的效果: 知己知彼,百战不殆.先来分析一 ...

  7. 纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!...

    前言 FineUI控件库发展至今已经有 5 个年头,目前论坛注册的QQ会员 5000 多人,捐赠用户 500 多人(捐赠用户转化率达到10%以上,在国内开源领域相信这是一个梦幻数字!也足以证明Fine ...

  8. canvas实现漂亮的下雨效果

    说明 这篇文章说如何用canvas画出漂亮的下雨效果,先看看最后实现的效果吧. 效果图 解释 看图来分析下,我们需要实现哪些效果. 1.雨滴下落效果,移动鼠标控制下落方向 2.雨滴下落散成小水珠,小水 ...

  9. 纯 CSS3 实现漂亮的 input 输入框

    分享一个用纯 CSS3 实现的,漂亮的 input 输入框动画样式库-Text input love. 点击每个输入框都用不同的动画效果,始终显示标签label,并显示 placeholder(占位符 ...

最新文章

  1. SAP 创建启用了ARM功能的采购订单,报错 -Shipping processing is not selected to supplier 100057 in purchase org. 0002
  2. rabbitmq beam.smp cpu利用率过高
  3. UNIX中的restrict
  4. 【Groovy】xml 序列化 ( 使用 MarkupBuilder 生成 xml 数据 | 设置 xml 标签内容 | 设置 xml 标签属性 )
  5. pytorch得到中间层输出
  6. 安装VCSA6.7(vCenter Server Appliance 6.7) 2019.7.9
  7. 行为型设计模式之解释器模式(Interpreter)
  8. xcode5切换IOS7,IOS6,IOS5模拟器
  9. BZOJ5248:[九省联考2018]一双木棋——题解
  10. C++ STL list的成员函数splice的使用
  11. matlab产生年月日的时间序列,求助:在MATLAB里如何输入时间序列中的时间
  12. Astar算法的Java实现 (其他很多都是错的,没有计入曼哈顿值的代价)
  13. python科赫雪花小包裹_034 实例8-科赫雪花小包裹-Go语言中文社区
  14. 探索性测试--极限测试法
  15. 限定通配符和非限定通配符_什么是通配符?
  16. Error connecting to node kafka:9092 (id: 1001 rack: null)
  17. 如何设置一个可扩展的MongoDB数据库?
  18. 02-vue(轮播图,v-bind对象用法,v-for指令,v-if指令,v-else-if,v-else指令,key值的基本使用,v-show指令,英雄搜索案例)
  19. 基于盲估计和ICA的单通道盲分离算法–Matlab仿真
  20. 双重差分法之安慰剂检验

热门文章

  1. 51单片机----Keil uVision程序编译软件与Proteus 8 Professional电路仿真软件之间调到统一频率(12MHz)
  2. ICS lab2: Defusing a Binary Bomb
  3. 如何学习前端-个人感悟
  4. 又是一年毕业季,分享自己在大学里的小打小闹经历
  5. PHPBB网站如何搬迁新服务器,phpbb3安装教程
  6. Qt Script(二)
  7. 计算机软硬件实训学什么,计算机软硬件实训报告.docx
  8. 中国无线电池监控系统市场趋势报告、技术动态创新及市场预测
  9. 【早餐组合(LCP-18-java)】
  10. 计算机配置很高 但是很卡,为什么你的电脑配置很高但是玩起游戏来还是很卡?-电脑很卡怎么办...