天天看點

HTML5 rotate 做儀表盤

 我們的項目中有關于資料倉庫和挖掘,使用者要求UI的界面需要儀表盤,我網上找了下,沒有發現免費的HTML儀表盤,餅圖啥圖表的确很多,那就沒有辦法了,我和同僚自己做了一個儀表盤,結果如下。

<a target="_blank" href="http://blog.51cto.com/attachment/201205/161746811.png"></a>

之後我們就來讨論下這個簡單的儀表盤是怎麼做的。我們先大緻有一個想法,設定一個寬高2:1的canvas,儀表盤的半徑就是canvas的高度,儀表盤需要的資料有上面分幾個區域(一般是低中高三個區域,為了測試我們準備了四個區域),刻度線和文字,指針,和指針指向的值。

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

[html] view plaincopy 

&lt;body&gt;  

&lt;div&gt;  

&lt;canvas id="board" width="800" height="600"&gt;  

&lt;/canvas&gt;  

&lt;/div&gt;  

&lt;/body&gt;  

&lt;/html&gt; 

之後的工作都在javascript中完成,我們需要定義一些對象

[javascript] view plaincopy 

//儀表盤面闆  

var panel = function(id, option) {  

this.canvas = document.getElementById(id); //擷取canvas元素  

thisthis.cvs = this.canvas.getContext("2d"); //得到繪制上下文  

thisthis.width = this.canvas.width; //對象寬度  

thisthis.height = this.canvas.height; //對象高度  

this.level = option.level;  

this.outsideStyle = option.outsideStyle;  

這個panel就是我們的儀表盤對象,參數的id是canvas元素,option是我們需要送出給儀表盤的一些參數值。這個option的定義如下:option對象可以擴充,你可以通過optin定制更加自由強大的儀表盤對象的。

var panelOption = {  

maxLength: 30,  

interval: 5,  

level: [//儀表盤需要呈現的資料隔離區域  

{start: 0, color: "red" },  

{ start: 30, color: "yellow" },  

{ start: 40, color: "blue" },  

{ start: 100, color: "Lime" }  

],  

outsideStyle: { lineWidth: 4, color: "rgba(100,100,100,1)" }  

}; 

在繪制元素的時候,我們常常需要儲存和恢複現場,特别當我們使用轉移,旋轉等方法的時候,一定要記得先save最後restore。為了友善,我們編寫了一個save函數提供這個方式,這個模式類似C#中的委托,和設計模式中的觀察着模式

panel.prototype.save = function(fn) {  

this.cvs.save();  

fn();  

this.cvs.restore();  

上面這個save可以友善的幫助我們儲存和回複現場。

我們定義個用于畫半圓的方法,這個方法中,我們将需要畫半圓時做的translate放到save函數中,這樣畫半圓的變形操作不會對其他操作有影響。

panel.prototype.drawArc = function() {  

var p = this;  

var cvs = this.cvs;  

p.save(function() {  

cvs.translate(p.width / 2, p.height); //将坐标點移到矩形的底部的中間  

cvs.beginPath();  

cvs.lineWidth = p.outsideStyle.lineWidth;  

cvs.strokeStyle = p.outsideStyle.color;  

cvs.arc(0, 0, p.height - cvs.lineWidth, 0, Math.PI / 180 * 180, true); //畫半圓  

cvs.stroke();  

});  

然後我們繪制中間顔色的填充區域

panel.prototype.drawLevelArea = function(level) {  

for (var i = 0; i &lt; level.length; i++) {  

cvs.translate(p.width / 2, p.height);  

cvs.rotate(Math.PI / 180 * level[i].start);  

cvs.arc(0, 0, p.height - p.outsideStyle.lineWidth, Math.PI / 180 * 180, Math.PI / 180 * 360);  

cvs.fillStyle = level[i].color;  

cvs.fill();  

}  

上面的代碼中,rotate很重要,我們每次都按level中的值進行旋轉,然後畫180°的顔色。這樣的過程是

第一次旋轉是0,沒有動,用紅色畫了180°的半圓

第二次旋轉了30°,你可以想想目前的畫布放斜了,然後以斜的畫了180°黃,這樣恰恰好吧紅色超過30°的顔色都覆寫了

依次類推,我們不要對arc的起始和結束值做改變,我們隻要再畫之前,rotate就可以了。當然,要放在save中哦。

之後是畫線,道理是一樣的,代碼如下

panel.prototype.drawLine = function() {  

for (var i = 0; i &lt;= 180; i++) {  

cvs.rotate(Math.PI / 180 * i);  

cvs.lineTo(-(p.height - p.outsideStyle.lineWidth) + 10, 0);  

cvs.lineTo(-(p.height - p.outsideStyle.lineWidth) + 5, 0);  

if (i % 10 == 0) {  

p.drawText(i);  

不過下面畫文字的代碼我沒有優化,你可以自己按上面的方式旋轉下

panel.prototype.drawText = function(val) {  

cvs.lineWidth = 1;  

cvs.strokeText(val, -(p.height - p.outsideStyle.lineWidth) + 5, 0);  

最後是畫指針,指針的角度值,是通過我們給的value來計算的。

panel.prototype.drawSpanner = function(value) {  

cvs.moveTo(0, 0);  

cvs.arc(0, 0, p.height / 30, 0, (Math.PI / 180) * 360);  

cvs.lineWidth = 3;  

cvs.rotate(Math.PI / 180 * -90);  

cvs.rotate(Math.PI / 180 * value);  

cvs.moveTo(5, -3);  

cvs.lineTo(0, -p.height * 0.7);  

cvs.lineTo(-5, -3);  

cvs.lineTo(5, -3);  

現在主要的方法都完成了,我們實作對使用者的接口

panel.prototype.init = function(value) {  

cvs.clearRect(0, 0, this.width, this.height);  

p.drawArc();  

p.drawLevelArea(p.level);  

p.drawLine();  

p.drawSpanner(value);  

到此,panel的對象我們都編寫完成,以下是如何調用

window.onload = function() {  

};  

Panel = new panel("board", panelOption);  

Panel.init(15);  

大家可以測試這個簡單的儀表盤了

本文轉自shyleoking 51CTO部落格,原文連結:http://blog.51cto.com/shyleoking/863987

繼續閱讀