ITに関するさまざまなトピックを紹介するサイトです
このコンテンツはお使いのブラウザには対応しておりません。
新しいバージョンのブラウザでアクセスしてください。

Canvasを利用した円グラフの描画


パネルのデータ欄に数値を入力すると、各データの割合に応じて円グラフが描画されます。
合計が100にならなくても構いません。
この円グラフ描画機能はクラス化しています。
  このページのコンテンツは、当初IEでは動作しないとしていました。
その後、IE9からIEでもCanvasに対応したことを知り、動作確認を行い表記を変更しました。
IE9標準モードで動きました。
データ1:
データ2:
データ3:
データ4:

コード

JavaScriptのコードは以下のようになっています。

ユーティリティ関数

/**
 * クロージャ関数を作成して返す。
 * @param {Function} func 実行する元の関数
 * @param {Object} obj 関数実行時のthis参照オブジェクト
 * @param {Object[]} [args] 実行する関数へ渡す引数の配列
 * @return {Object} 実行した関数の戻り値
 */
function closure(func, obj, args) {
	var closureFunc = function() {
		var comboArgs = new Array();
		if (args != null && (typeof args == "object")) {
			comboArgs = comboArgs.concat(args);
		}
		comboArgs = comboArgs.concat(Array.prototype.slice.call(arguments));
		return func.apply(obj, comboArgs);
	};
	return closureFunc;
};

円グラフ描画クラス

/**
 * 円グラフ描画クラス
 * @constructor
 * @param {String} canvasId キャンバス要素のID
 * @param {Number} dataNum データ数
 * @param {String} dataName データ名(要素のIDの先頭の共通名)
 * @param {String[]} colors 円弧の塗りつぶし色の配列
 */
function DrawCanvasCircleGraph(canvasId, dataNum, dataName, colors) {
	this.canvas = document.getElementById(canvasId);
	if (!this.canvas) {
		return;
	}

	this.dataNum = dataNum || 0;
	this.dataName = dataName;
	if (colors != null && typeof colors == "object") {
		this.colors = colors;
	} else {
		this.colors = new Array();
	}

	//中心点座標X
	this.centerX = parseInt(this.canvas.width / 2, 10) || 100;
	//中心点座標Y
	this.centerY = parseInt(this.canvas.height / 2, 10) || 100;
	//半径
	this.radius = parseInt(Math.min(this.centerX, this.centerY) * 0.8, 10);
};

/**
 * データを取得して円グラフを描画する。
 */
DrawCanvasCircleGraph.prototype.prepareArc = function() {
	if (!this.canvas) {
		return;
	}

	var elem;
	var value;
	var data = new Array();
	for (var i = 0; i < this.dataNum; i++) {
		//データ値を格納しているDOM要素を取得(idはデータ名の末尾に1からの連番を追加したもの)
		elem = document.getElementById(this.dataName + (i+1));
		value = (elem) ? (elem.value ? elem.value : 0) : 0;
		data.push(parseFloat(value));
	}
	this.drawArc(data);
};

/**
 * 円グラフを描画する。
 * @param {Number[]} data 描画データの配列
 */
DrawCanvasCircleGraph.prototype.drawArc = function(data) {
	if (!this.canvas) {
		return;
	}

	if (data == null || typeof data != "object" || data.length == 0) {
		return;
	}
	var total = this.sumData(data);
	if (total == 0) {
		return;
	}

	var ctxt = this.canvas.getContext("2d");

	var arcs = new Array();
	var currAngle = 0;
	var pct;

	//円グラフの円弧に対応する値を計算する
	for (var i = 0; i < data.length; i++) {
		pct = data[i] / total;
		arcs[i] = {
			startAngle : currAngle * Math.PI * 2,
			endAngle : (currAngle += pct) * Math.PI * 2
		};
	}

	//円グラフの円弧を描画する
	ctxt.save();
	for (var i = 0; i < arcs.length; i++) {
		if (data[i] == 0) {
			continue;
		}
		ctxt.fillStyle = this.colors[i] ||
				"rgb(" + parseInt(Math.random() * 255, 10)
				+ "," + parseInt(Math.random() * 255, 10)
				+ "," + parseInt(Math.random() * 255, 10) + ")";
		ctxt.beginPath();
		ctxt.moveTo(this.centerX, this.centerY);
		ctxt.arc(this.centerX, this.centerY, this.radius,
				arcs[i].startAngle - Math.PI / 2,
				arcs[i].endAngle - Math.PI / 2,
				false);
		ctxt.closePath();
		ctxt.fill();
	}
	ctxt.restore();
};

/**
 * データの総合計を計算する。
 * @param {Number[]} data 描画データの配列
 * @return {Number} データの総合計
 */
DrawCanvasCircleGraph.prototype.sumData = function(data) {
	var result = 0;
	for (var i = 0; i < data.length; i++) {
		result += parseFloat(data[i]);
	}
	return result;
};

ページ読み込み時の処理

var drawCircle;

$(function() {
	// Canvasのサイズ設定
	var boxSize = $("#canvas_wrapper").width();
	$("#myCanvas").attr("width", boxSize);
	$("#myCanvas").attr("height", boxSize);

	// 円描画インスタンス生成
	drawCircle = new DrawCanvasCircleGraph("myCanvas", 4, "graphData",
			["#ff6666", "#66ff66", "#6666ff", "#ffff66"]);

	// データ変更リスナ設定
	for (var i = 0; i < 4; i++) {
		$("#graphData" + (i+1)).change(closure(drawCircle.prepareArc, drawCircle));
	}

	// 円描画実行
	drawCircle.prepareArc();
});

当サイトでは、第三者配信による広告サービスを利用しています。 このような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報(氏名、住所、メール アドレス、電話番号は含まれません)を使用することがあります。 このプロセスの詳細やこのような情報が広告配信事業者に使用されないようにする方法については、こちらをクリックしてください。