2014年4月10日木曜日

html5のcanvasにレーダーチャートを描画する

レーダーチャートの話が仕事中に出て自前で作るかどこかのコンポーネントを購入するかという話になり結局購入することになったのだけれども、デモ用にちゃちゃっとレーダーチャートを実装したのがあるので公開しておく。

デモはこちら

実装周り
// Knockoutjs周りは省略

var canvas = document.getElementById("canvas")
 , c = canvas.getContext("2d");
function drawRader(){
 var points = viewModel.points()
    , eachRad = (Math.PI*2) / points.length
 , i
 , accumRad = Math.PI/2
 , radius = 150
 , center = 200
 , sin
 , cos
    , endOfAxisPt
 , firstPt
 , prevPt
 , currentPt;
 c.clearRect(0,0,400,400);
 for(i = 0; i < points.length; i ++){
  c.strokeStyle = "#ffa500";
  c.beginPath();
  sin = Math.sin(accumRad);
  cos = Math.cos(accumRad);
        endOfAxisPt = {
            x: center + (cos * radius),  
            y: center - (sin * radius)
        };
  accumRad += eachRad;
  c.moveTo(center, center);
  c.lineTo(endOfAxisPt.x, endOfAxisPt.y);
  c.stroke();
        
        c.fillStyle = "#00A0E9";
        c.fillText(points[i].text(),
                   endOfAxisPt.x - 10, 
                   endOfAxisPt.y - (sin * 20));
  
  c.strokeStyle = "#00A0E9";
  c.beginPath();
  currentPt = { 
    x: center + (cos * (radius * points[i].ratio())), 
    y: center - (sin * (radius * points[i].ratio())) 
   };
  if(prevPt){   
   c.moveTo(prevPt.x, prevPt.y);
   c.lineTo(currentPt.x, currentPt.y);
  }
  else
   firstPt = currentPt;
  prevPt = currentPt;  
  c.stroke();
 } 
  
 c.beginPath();
 c.moveTo(prevPt.x, prevPt.y);
 c.lineTo(firstPt.x, firstPt.y);
 c.stroke();
}
drawRader();
drawRader()の冒頭でviewModel.points()と取得しているのはKnockoutjs用のViewModelが内部的に保持しているObservableArrayだ(Knockoutjsを知らない人は配列のようなものと考えてもらって構わない)。描画の処理は単純で配列のアイテム数で360度を割ってその角度ごとに軸線を描画し、前後の軸線上の点と点を結んでいくだけ。