博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTML5 rotate 做仪表盘
阅读量:7260 次
发布时间:2019-06-29

本文共 4500 字,大约阅读时间需要 15 分钟。

 我们的项目中有关于数据仓库和挖掘,用户要求UI的界面需要仪表盘,我网上找了下,没有发现免费的HTML仪表盘,饼图啥图表的确很多,那就没有办法了,我和同事自己做了一个仪表盘,结果如下。

 

之后我们就来讨论下这个简单的仪表盘是怎么做的。我们先大致有一个想法,设定一个宽高2:1的canvas,仪表盘的半径就是canvas的高度,仪表盘需要的数据有上面分几个区域(一般是低中高三个区域,为了测试我们准备了四个区域),刻度线和文字,指针,和指针指向的值。

首先第一步自然是canvas的声明

 
  1. [html] view plaincopy 
  2. <body>  
  3. <div>  
  4. <canvas id="board" width="800" height="600">  
  5. </canvas>  
  6. </div>  
  7. </body>  
  8. </html> 

之后的工作都在javascript中完成,我们需要定义一些对象

 
  1. [javascript] view plaincopy 
  2. //仪表盘面板  
  3. var panel = function(id, option) {  
  4. this.canvas = document.getElementById(id); //获取canvas元素  
  5. thisthis.cvs = this.canvas.getContext("2d"); //得到绘制上下文  
  6. thisthis.width = this.canvas.width; //对象宽度  
  7. thisthis.height = this.canvas.height; //对象高度  
  8. this.level = option.level;  
  9. this.outsideStyle = option.outsideStyle;  

这个panel就是我们的仪表盘对象,参数的id是canvas元素,option是我们需要提交给仪表盘的一些参数值。这个option的定义如下:option对象可以扩展,你可以通过optin定制更加自由强大的仪表盘对象的。

 
  1. [javascript] view plaincopy 
  2. var panelOption = {  
  3. maxLength: 30,  
  4. interval: 5,  
  5. level: [//仪表盘需要呈现的数据隔离区域  
  6. {start: 0, color: "red" },  
  7. { start: 30, color: "yellow" },  
  8. { start: 40, color: "blue" },  
  9. { start: 100, color: "Lime" }  
  10. ],  
  11. outsideStyle: { lineWidth: 4, color: "rgba(100,100,100,1)" }  
  12. }; 

在绘制元素的时候,我们常常需要保存和恢复现场,特别当我们使用转移,旋转等方法的时候,一定要记得先save最后restore。为了方便,我们编写了一个save函数提供这个方式,这个模式类似C#中的委托,和设计模式中的观察着模式

 
  1. [javascript] view plaincopy 
  2. panel.prototype.save = function(fn) {  
  3. this.cvs.save();  
  4. fn();  
  5. this.cvs.restore();  

上面这个save可以方便的帮助我们保存和回复现场。

我们定义个用于画半圆的方法,这个方法中,我们将需要画半圆时做的translate放到save函数中,这样画半圆的变形操作不会对其他操作有影响。

 
  1. [javascript] view plaincopy 
  2. panel.prototype.drawArc = function() {  
  3. var p = this;  
  4. var cvs = this.cvs;  
  5. p.save(function() {  
  6. cvs.translate(p.width / 2, p.height); //将坐标点移到矩形的底部的中间  
  7. cvs.beginPath();  
  8. cvs.lineWidth = p.outsideStyle.lineWidth;  
  9. cvs.strokeStyle = p.outsideStyle.color;  
  10. cvs.arc(0, 0, p.height - cvs.lineWidth, 0, Math.PI / 180 * 180, true); //画半圆  
  11. cvs.stroke();  
  12. });  

然后我们绘制中间颜色的填充区域

 
  1. [javascript] view plaincopy 
  2. panel.prototype.drawLevelArea = function(level) {  
  3. var p = this;  
  4. var cvs = this.cvs;  
  5. for (var i = 0; i < level.length; i++) {  
  6. p.save(function() {  
  7. cvs.translate(p.width / 2, p.height);  
  8. cvs.rotate(Math.PI / 180 * level[i].start);  
  9. p.save(function() {  
  10. cvs.beginPath();  
  11. cvs.arc(0, 0, p.height - p.outsideStyle.lineWidth, Math.PI / 180 * 180, Math.PI / 180 * 360);  
  12. cvs.fillStyle = level[i].color;  
  13. cvs.fill();  
  14. });  
  15. });  
  16. }  

上面的代码中,rotate很重要,我们每次都按level中的值进行旋转,然后画180°的颜色。这样的过程是

第一次旋转是0,没有动,用红色画了180°的半圆

第二次旋转了30°,你可以想想目前的画布放斜了,然后以斜的画了180°黄,这样恰恰好吧红色超过30°的颜色都覆盖了

依次类推,我们不要对arc的起始和结束值做改变,我们只要再画之前,rotate就可以了。当然,要放在save中哦。

之后是画线,道理是一样的,代码如下

 
  1. [javascript] view plaincopy 
  2. panel.prototype.drawLine = function() {  
  3. var p = this;  
  4. var cvs = this.cvs;  
  5. for (var i = 0; i <= 180; i++) {  
  6. p.save(function() {  
  7. cvs.translate(p.width / 2, p.height);  
  8. cvs.rotate(Math.PI / 180 * i);  
  9. p.save(function() {  
  10. cvs.beginPath();  
  11. cvs.lineTo(-(p.height - p.outsideStyle.lineWidth) + 10, 0);  
  12. cvs.lineTo(-(p.height - p.outsideStyle.lineWidth) + 5, 0);  
  13. cvs.stroke();  
  14. if (i % 10 == 0) {  
  15. p.drawText(i);  
  16. }  
  17. });  
  18. });  
  19. }  

不过下面画文字的代码我没有优化,你可以自己按上面的方式旋转下

 
  1. [javascript] view plaincopy 
  2. panel.prototype.drawText = function(val) {  
  3. var p = this;  
  4. var cvs = this.cvs;  
  5. p.save(function() {  
  6. cvs.lineWidth = 1;  
  7. cvs.strokeText(val, -(p.height - p.outsideStyle.lineWidth) + 5, 0);  
  8. });  

最后是画指针,指针的角度值,是通过我们给的value来计算的。

 
  1. [javascript] view plaincopy 
  2. panel.prototype.drawSpanner = function(value) {  
  3. var p = this;  
  4. var cvs = this.cvs;  
  5. p.save(function() {  
  6. cvs.translate(p.width / 2, p.height);  
  7. cvs.moveTo(0, 0);  
  8. cvs.arc(0, 0, p.height / 30, 0, (Math.PI / 180) * 360);  
  9. cvs.lineWidth = 3;  
  10. cvs.stroke();  
  11. });  
  12.  
  13. p.save(function() {  
  14. cvs.translate(p.width / 2, p.height);  
  15. cvs.rotate(Math.PI / 180 * -90);  
  16. p.save(function() {  
  17. cvs.rotate(Math.PI / 180 * value);  
  18. cvs.beginPath();  
  19. cvs.moveTo(5, -3);  
  20. cvs.lineTo(0, -p.height * 0.7);  
  21. cvs.lineTo(-5, -3);  
  22. cvs.lineTo(5, -3);  
  23. cvs.fill();  
  24. });  
  25. });  

现在主要的方法都完成了,我们实现对用户的接口

 
  1. [javascript] view plaincopy 
  2. panel.prototype.init = function(value) {  
  3. var p = this;  
  4. var cvs = this.cvs;  
  5. cvs.clearRect(0, 0, this.width, this.height);  
  6.  
  7. p.drawArc();  
  8. p.drawLevelArea(p.level);  
  9. p.drawLine();  
  10. p.drawSpanner(value);  

到此,panel的对象我们都编写完成,以下是如何调用

 
  1. [javascript] view plaincopy 
  2. window.onload = function() {  
  3. var panelOption = {  
  4. maxLength: 30,  
  5. interval: 5,  
  6. level: [//仪表盘需要呈现的数据隔离区域  
  7. {start: 0, color: "red" },  
  8. { start: 30, color: "yellow" },  
  9. { start: 40, color: "blue" },  
  10. { start: 100, color: "Lime" }  
  11. ],  
  12. outsideStyle: { lineWidth: 4, color: "rgba(100,100,100,1)" }  
  13. };  
  14.  
  15. Panel = new panel("board", panelOption);  
  16. Panel.init(15);  

大家可以测试这个简单的仪表盘了

本文转自shyleoking 51CTO博客,原文链接:http://blog.51cto.com/shyleoking/863987

转载地址:http://akudm.baihongyu.com/

你可能感兴趣的文章
最新2018年全球DevOps薪资报告:行业和团队选择指南
查看>>
Visual Studio 15.4发布,新增多平台支持
查看>>
Swift和Objective-C的运行时编程
查看>>
OneAPM挂牌新三板,续写ITOM新篇章
查看>>
KubeEdge:开源的Kubernetes原生边缘计算框架
查看>>
Stefan Tilkov:跳过单体应用,从微服务开始
查看>>
华为2018:年收入首破千亿美元大关,研发投入过千亿
查看>>
云计算怎么支撑起《流浪地球》的硬科幻实力?
查看>>
微服务基础架构的5个关键问题
查看>>
Git漏洞导致攻击者可在用户电脑上运行任意代码
查看>>
360首席安全官谭晓生宣布离职
查看>>
《与编码人员一起工作》作者访谈
查看>>
编写Linux内核模块——第一部分:前言
查看>>
python学习笔记 - StringIO以及BytesIO
查看>>
消息称微软计划收购GitHub,估值超50亿美元
查看>>
Netflix Play API:我们为什么构建了一个演进式架构?
查看>>
知乎推荐页Ranking构建历程和经验分享
查看>>
Web性能API——帮你分析Web前端性能
查看>>
Swift 4正式发布,新功能概览
查看>>
谈谈基于机器学习的编程到底比传统编程强在哪里?
查看>>