canvas仿芝麻信用分儀表盤

rmfi6531 8年前發布 | 13K 次閱讀 前端技術 canvas

這是一個仿支付寶芝麻信用分的一個canvas,其實就是一個動畫儀表盤。

首先, 上原圖:

這個是在下支付寶上的截圖,分低各位見笑了。然后看下我用canvas實現的效果圖:

<canvas id="canvas" width="400" height="700" data-score='724'></canvas>
<!-- 設置data-score,分數區間[400, 900] -->

唉,總感覺不像。這個是GIF圖,可能在網頁上打開的效果會好一點(

當然可能就是這樣

)。大家可以點擊底部預覽codepen上的演示。有兩個不完美的地方,一個是實際上芝麻信用表盤上的的刻度是不均勻的,我這為了簡單的實現就采取相同的刻度;二是表盤上運動的點是有模糊的效果,還沒解決。唉,下次再說吧。

接下來還是來說說怎么實現的吧。第一步,國際慣例,創建畫布:

var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    cWidth = canvas.width,
    cHeight = canvas.height;

然后繪制表盤,雖說不是處女座,但也要盡可能做到跟原圖上的一樣,那就是這個環形開口的角度是多少呢?請上ps來測一下:

嗯,136°,這個角度確實刁鉆,為了方便接下來的計算,那就約等于140°。那么一個分數段的弧度就是:

var deg1 = Math.PI * 11 / 45

先把中間半透明的刻度層畫好:

ctx.save(); //中間刻度層
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(0, 0, 135, 0, 11 * deg0, false);
ctx.stroke();
ctx.restore();

接著,畫6條刻度線,用for循環來實現:

ctx.save(); // 刻度線
for (var i = 0; i < 6; i++) {
  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
  ctx.moveTo(140, 0);
  ctx.lineTo(130, 0);
  ctx.stroke();
  ctx.rotate(deg1);
}
ctx.restore();

同理,再把大刻度細分為5個小刻度:

ctx.save(); // 細分刻度線
for (i = 0; i < 25; i++) {
  if (i % 5 !== 0){
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'rgba(255, 255, 255, .1)';
    ctx.moveTo(140, 0);
    ctx.lineTo(133, 0);
    ctx.stroke();
  }
  ctx.rotate(deg1 / 5);
}
ctx.restore();

刻度到這里就ok了,還需要給刻度標上文字和每個分數段的信用級別,具體的參見代碼,因為跟刻度實現的原理差不多,就不啰嗦了。現在最關鍵就是實現表盤上那個運動的點(不知道怎么稱呼,下文就叫它動點),我們可以這樣想,它是個半徑很小的圓,只不過是畫在最外層環形軌道上圓,而圓在 canvas 上的實現方法是:

ctx.arc(x, y, radius, sAngle, eAngle, false);

我們只要控制x, y就能讓它動起來,實現我們想要的效果。so,創建一個動點對象:

function Dot() {
  this.x = 0;
  this.y = 0;
  this.draw = function (ctx) {
    ctx.save();
    ctx.beginPath();
    ctx.fillStyle = 'rgba(255, 255, 255, .7)';
    ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
    ctx.fill();
    ctx.restore();
  };
}
var dot = new Dot(),
    dotSpeed = 0.03, //控制動點的速度
    angle = 0, //這個很關鍵,用來得到動點的坐標x, y
    credit = 400; //信用最低分數

如何得到dot的坐標x, y呢?那就要用到傳說中三角函數了。

通過上圖我們可以得到

x = r * cos(angle), y = r * sin(angle)

在JavaScript中,dot的中心坐標就變成了:

dot.x = radius * Math.cos(angle); //radius為最外層軌道的半徑值
dot.y = radius * Math.sin(angle);

接下來我們只要得到這個angle。這個通過弧度與分數的比例關系就可以得到:

var aim = (score - 400) * deg1 / 100;
if (angle < aim) {
  angle += dotSpeed;
}
dot.draw(ctx);

然后讓中間的信用分數也能隨動點的轉動而變化,創建一個 text() ,為了使數字變化能和動點保持一致,要根據動點的速率來計算數字變化:

function text(process) {
  ctx.save();
  ctx.rotate(10 * deg0);
  ctx.fillStyle = '#000';
  ctx.font = '80px Microsoft yahei';
  ctx.textAlign = 'center';
  ctx.textBaseLine = 'top';
  ctx.fillText(process, 0 ,10);
  ctx.restore();
}
var textSpeed = Math.round(dotSpeed * 100 / deg1),
if (credit < score - textSpeed) {
  credit += textSpeed;
} else if (credit >= score - textSpeed && credit < score) {
  credit += 1; // 這里確保信用分數最后停下來是我們輸入的分數
}
text(credit);

最后這一切都逃不過讓window.requestAnimationFrame()來控制繪制動畫和用ctx.clearRect(0, 0, cWidth, cHeight)來清除畫布。

 

 

來自:http://www.cnblogs.com/libin-1/p/6068340.html

 

 本文由用戶 rmfi6531 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!