D3.jsの基本 | 円を描く

D3.jsは、特にグラフ系の図をSVG画像として作図するのを得意としている。
グラフ用のデータを用意し、それをグラフ作図処理に流すというのが基本である。

デモ

JavaScript


	$(function(){
	
		// データ
		var dataset = [ 30, 60, 90, 120 ];
		
		// SVGタグを作成する
		var svg = d3.select("#demo").append("svg");
		
		// SVGの幅を設定する
		svg.attr("width", 500)
			.attr("height", 450);
		
		// 円の基礎(circle)とデータをSVGにセットする。
		var circles = svg.selectAll("circle")
			.data(dataset)
			.enter()
			.append("circle");

		// 円へデータの値を元に位置および半径を設定していく。
		circles.attr("cx", function(d, i) {
				return d;// dはデータ(dataset)の値要素である。
			})
			.attr("cy", 90)
			.attr("r", 8);

	});	
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力



参考サイト


矩形シェイプを描く

D3.jsで矩形を描画してみる。
デモ

JavaScript


	// データ
	var dataset = [ 100, 200, 300, 400 ];
	
	// SVGタグを作成する
	var svg = d3.select("#demo").append("svg");
	
	// SVGの幅を設定する
	svg.attr("width", 500)
		.attr("height", 450);
	
	// 矩形の基礎(rect)とデータをSVGにセットする。
	var rect = svg.selectAll(".rect1")
		.data(dataset)
		.enter()
		.append("rect");

	// 矩形へデータの値を元に位置および半径を設定していく。
	rect
		.attr('class','rect1')
		.attr("x", function(d, i) {
			return d;
		})
		.attr("y", 90)
		.attr("width", 80)
		.attr("height", 60)
		.attr("rx", 5)
		.attr("fill", 'none')
		.attr("stroke", '#8ca934')
		.attr("stroke-width", 4)
		;
	

SVGの出力




シェイプをグループでまとめる

SVGには子要素の概念がないように思えるが、 代わりにグループという概念が存在する。
SVGではグループを<g>として表されている。 D3.jsでグループを取り扱う場合、データのひもづけ(バインディング)は”グループ”に対して行う。

デモ

JavaScript


	// エンティティ配列のデータ
	var dataset = [
		{'x':100 , 'name':'ネコ'},
		{'x':200 , 'name':'ヤギ'},
		{'x':300 , 'name':'カニ'},
		{'x':400 , 'name':'サメ'},
	];
	
	// SVGタグを作成する
	var svg = d3.select("#demo").append("svg");
	
	// SVGの幅を設定する
	svg.attr("width", 500)
		.attr("height", 450);
	
	// グループ要素を作成し、データをひもづける。
	var group1 = svg.selectAll(".group1")
		.data(dataset)
		.enter()
		.append("g");
	
	// グループに矩形を追加する。
	var rect = group1.append("rect");
	
	// 矩形を設定、およびデータを適用する。
	rect
		.attr('class','rect1')
		.attr("x", function(d, i) {
			return d.x;
		})
		.attr("y", 90)
		.attr("width", 80)
		.attr("height", 60)
		.attr("rx", 5)
		.attr("fill", 'none')
		.attr("stroke", '#8ca934')
		.attr("stroke-width", 4)
		;
	
	// グループにテキストを追加する。
	var text1 = group1.append("text");
	
	// テキストの設定、およびデータを適用する。
	text1
		.attr('class','text1')
		.attr("x", function(d, i) {
			return d.x + 20;
		})
		.attr("y", 110)
		.attr("fill", 'red')
		.text(function(d, i) {
			return d.name;
		})
		;
	

SVGの出力




文字列をリンク化してみる


デモ

JavaScript


	$(function(){
		
		// エンティティ配列のデータ
		var dataset = [
			{'x':100 , 'name':'google' , 'url':'https://www.google.co.jp/'},
			{'x':200 , 'name':'yahoo' , 'url':'https://www.yahoo.co.jp/'},
			{'x':300 , 'name':'天気' , 'url':'http://www.jma.go.jp/jp/g3/'},
			{'x':400 , 'name':'自身' , 'url':'http://www.jma.go.jp/jp/quake/'},
		];
		
		// SVGタグを作成する
		var svg = d3.select("#demo").append("svg");
		
		// SVGの幅を設定する
		svg.attr("width", 500)
			.attr("height", 450);
		
		// グループ要素を作成し、データをひもづける。
		var group1 = svg.selectAll(".group1")
			.data(dataset)
			.enter()
			.append("g");
		
		// グループに矩形を追加する。
		var rect = group1.append("rect");
		
		// 矩形を設定、およびデータを適用する。
		rect
			.attr('class','rect1')
			.attr("x", function(d, i) {
				return d.x;
			})
			.attr("y", 90)
			.attr("width", 80)
			.attr("height", 60)
			.attr("rx", 5)
			.attr("fill", 'none')
			.attr("stroke", '#8ca934')
			.attr("stroke-width", 4)
			;

		
		// グループにテキストを追加する。
		var text1 = group1.append("text")
			.attr('class','text1')
			.attr("x", function(d, i) {
				return d.x + 20;
			})
			.attr("y", 110)
			;
		
		// テキスト要素内にアンカータグを追加し、それにURLを設定する
		var a1 = text1.append("a")
			.attr('xlink:href', function(d, i) {
				return d.url;
			})
			.attr("fill", 'green')
			.text(function(d, i) {
				return d.name;
			})
			;
			
			
	});
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力




リンクをBootstrapでボタン化してみる

ボタン化できない。SVGにはBootstrapは適応できない?
しかし、通常のリンクと同様、ページ遷移キャンセルしてonclickイベントを組み込むことは可能である。


デモ

JavaScript


	$(function(){
	
		// エンティティ配列のデータ
		var dataset = [
			{'x':100 , 'name':'ネコ'},
			{'x':200 , 'name':'ヤギ'},
			{'x':300 , 'name':'カニ'},
			{'x':400 , 'name':'サメ'},
		];
		
		// SVGタグを作成する
		var svg = d3.select("#demo").append("svg");
		
		// SVGの幅を設定する
		svg.attr("width", 500)
			.attr("height", 450);
		
		// グループ要素を作成し、データをひもづける。
		var group1 = svg.selectAll(".group1")
			.data(dataset)
			.enter()
			.append("g");
		
		// グループに矩形を追加する。
		var rect = group1.append("rect");
		
		// 矩形を設定、およびデータを適用する。
		rect
			.attr('class','rect1')
			.attr("x", function(d, i) {
				return d.x;
			})
			.attr("y", 90)
			.attr("width", 80)
			.attr("height", 60)
			.attr("rx", 5)
			.attr("fill", 'none')
			.attr("stroke", '#8ca934')
			.attr("stroke-width", 4)
			;

		// グループにテキストを追加する。
		var text1 = group1.append("text")
			.attr('class','text1')
			.attr("x", function(d, i) {
				return d.x + 20;
			})
			.attr("y", 110)
			;
		
		// テキスト要素内にアンカータグを追加し、それにURLを設定する
		var a1 = text1.append("a")
			.attr('xlink:href', function(d, i) {
					return 'javascript:void(0)';
				})
				.attr("onclick", "alert('test=');")
				.attr("class", "btn btn-info")
			.attr("fill", 'green')
			.text(function(d, i) {
				return d.name;
			})
			;
			
			
	});
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力




ラインを描画する


デモ

JavaScript


	$(function(){
	
		// エンティティ配列のデータ
		var dataset = [
			{'lineData':[[100,100],[200,100]] ,'color':'red'},
			{'lineData':[[100,120],[200,120]] ,'color':'green'},
			{'lineData':[[100,140],[200,140]] ,'color':'yellow'},
			{'lineData':[[100,160],[200,160]] ,'color':'blue'},
		];
		
	
		// SVGタグを作成する
		var svg = d3.select("#demo").append("svg");
		
		// SVGの幅を設定する
		svg.attr("width", 640)
			.attr("height", 480);
	
		// line変換関数: 線の配列をpathのd属性形式に変換する
		var lineArrToD = d3.line()
			.x(function(d) {return d[0];})
			.y(function(d) {return d[1];});
		
		// 線(path)を追加する
		var line1 = svg.selectAll(".path1")
			.data(dataset)
			.enter()
			.append("path");
		
		// 線にデータを適用する
		line1
			.attr('d',function(d, i) {
				d = lineArrToD(d.lineData);
				return d;
			})
			.attr('stroke',function(d, i) {
				return d.color;
			})
			.attr('stroke-width',4)
		;
			
			
	});
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力




半透明のラインを描画

色コードにα値を追加することで半透明を実現できる。
rgba(0,0,255,0.5)
α値は0~1の範囲で指定する。

デモ

JavaScript


	// エンティティ配列のデータ
	var dataset = [
		{'lineData':[[100,100],[200,100]] ,'color':'red'},
		{'lineData':[[100,120],[200,120]] ,'color':'green'},
		{'lineData':[[100,140],[200,140]] ,'color':'yellow'},
		{'lineData':[[100,160],[200,50]] ,'color':'rgba(0,0,255,0.5)'},
	];
	

	// SVGタグを作成する
	var svg = d3.select("#demo").append("svg");
	
	// SVGの幅を設定する
	svg.attr("width", 640)
		.attr("height", 480);

	// line変換関数: 線の配列をpathのd属性形式に変換する
	var lineArrToD = d3.line()
		.x(function(d) {return d[0];})
		.y(function(d) {return d[1];});
	
	// 線(path)を追加する
	var line1 = svg.selectAll(".path1")
		.data(dataset)
		.enter()
		.append("path");
	
	// 線にデータを適用する
	line1
		.attr('d',function(d, i) {
			d = lineArrToD(d.lineData);
			return d;
		})
		.attr('stroke',function(d, i) {
			return d.color;
		})
		.attr('stroke-width',10)
	;
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力




ベジエ曲線


デモ

JavaScript


	// エンティティ配列のデータ
	var dataset = [
		{'lineData':[[100,100],[200,100],[300,150]] ,'color':'red'},
		{'lineData':[[100,120],[200,120],[300,170]] ,'color':'green'},
		{'lineData':[[100,140],[200,140],[300,190]] ,'color':'yellow'},
		{'lineData':[[100,160],[200,50],[300,150]] ,'color':'rgba(0,0,255,0.5)'},
	];
	

	// SVGタグを作成する
	var svg = d3.select("#demo").append("svg");
	
	// SVGの幅を設定する
	svg.attr("width", 640)
		.attr("height", 280);


	// line変換関数: 線の配列をpathのd属性形式に変換する
	var lineArrToD = d3.line()
		.curve(d3.curveBasis)
		.x(function(d) {return d[0];})
		.y(function(d) {return d[1];});
	
	// 線(path)を追加する
	var line1 = svg.selectAll(".path1")
		.data(dataset)
		.enter()
		.append("path");
	
	// 線にデータを適用する
	line1
		.attr('d',function(d, i) {
			d = lineArrToD(d.lineData);
			return d;
		})
		.attr('stroke',function(d, i) {
			return d.color;
		})
		.attr('stroke-width',10)
		.attr('fill','none')
	;
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力




d3.line()のcurveで指定できる曲線の種類
d3.line().curve(〇〇〇)説明
d3.curveLinearデフォルト(ただの直線の組み合わせ)
d3.curveStepステップ関数(垂直の線)
d3.curveStepBeforeステップ関数(曲がり箇所がそろっている)
d3.curveStepAfterステップ関数(d3.curveStepBeforeの逆曲がり)
d3.curveBasisベジエ曲線
d3.curveCardinalなめらかな急カーブ
d3.curveMonotoneXベジエより山なりのカーブになる(d3.curveCardinalよりは緩やか)
d3.curveCatmullRomd3.curveCardinalとよく似ているが、検証不足のため違いは分からず。

文字列の幅取得


JavaScript


	// エンティティ配列のデータ
	var dataset = [
		{'x':100 , 'name':'ネコ'},
		{'x':200 , 'name':'山羊'},
		{'x':300 , 'name':'ケガニ'},
		{'x':400 , 'name':'ホホジロザメ'},
	];
	
	// SVGタグを作成する
	var svg = d3.select("#demo").append("svg");
	
	// SVGの幅を設定する
	svg.attr("width", 500)
		.attr("height", 450);
	

	// テキストメジャー: テキストの幅を取得するためのテキスト要素
	var text_measure = svg.append("text")
		.attr("id", 'text_measure');
	
	
	for(var i in dataset){
		var d = dataset[i];

		text_measure.text(d.name);
		var textSizeInfo = text_measure.node().getBBox();
		console.log(textSizeInfo);
		
	}
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

コンソール出力




多次元配列のデータセットを出力


デモ

2次元以降のsubDataを出力してみる。

JavaScript


	// エンティティ配列のデータ
	var dataset = [
		{'x':100 , 'kind':'哺乳類',
			'subData':[
				{'index1':0 , 'animal_name':'マヤー'},
				{'index1':0 , 'animal_name':'アグー'},
				{'index1':0 , 'animal_name':'マングース'},
			],
		},
		{'x':200 , 'kind':'魚類',
			'subData':[
				{'index1':1 , 'animal_name':'グルクン'},
				{'index1':1 , 'animal_name':'アカジン'},
			],
		},
		{'x':300 , 'kind':'両生類',
			'subData':[
				{'index1':2 , 'animal_name':'イボイモリ'},
				{'index1':2 , 'animal_name':'ハナサキガエル'},
				{'index1':2 , 'animal_name':'イシカワガエル'},
				{'index1':2 , 'animal_name':'シリケンイモリ'},
			],
		},
	];
	
	// SVGタグを作成する
	var svg = d3.select("#demo").append("svg");
	
	// SVGの幅を設定する
	svg.attr("width", 500)
		.attr("height", 600);
	
	// グループ要素を作成し、データをひもづける。
	var group1 = svg.selectAll(".group1")
		.data(dataset)
		.enter()
		.append("g");
	
	// グループに矩形を追加する。
	var rect = group1.append("rect");
	
	// 矩形を設定、およびデータを適用する。
	rect
		.attr('class','rect1')
		.attr("x", function(d, i) {
			return d.x;
		})
		.attr("y", 90)
		.attr("width", 90)
		.attr("height", 120)
		.attr("rx", 5)
		.attr("fill", 'none')
		.attr("stroke", '#8ca934')
		.attr("stroke-width", 4)
		;
	
	// グループにテキストを追加する。
	var text1 = group1.append("text");
	
	// テキストの設定、およびデータを適用する。
	text1
		.attr('class','text1')
		.attr("x", function(d, i) {

			return d.x + 20;
		})
		.attr("y", 110)
		.attr("fill", 'red')
		.text(function(d, i) {
			return d.kind;
		})
		;
	
	
	// 2次元要素であるsubDataの出力
	var sub_text = group1.selectAll(".animal_name")
		.data(function(d) {return d.subData}) 
		.enter()
		.append('text');
	
	sub_text
		.attr("fill", 'blue')
		.attr("font-size", 11)
		.attr("x", function(d, i) {
			
			var row = dataset[d.index1];
			
			return row.x + 20;
		})
		.attr("y", function(d, i) {

			return (i * 20) + 140;
			
		})
		.text(function(d, i) {
			return d.animal_name;
		})
		;
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力




スケール


JavaScript


	var xScale = d3.scaleLinear()
		.domain([0, 640])
		.range([0, 320]);
	
	console.log(xScale(12)); // → 6
	

応用は下記のデモを参考
デモ


矢印


デモ

JavaScript


	$(function(){
		createSvg(1);
	});
	
	function createSvg(scale_rate){
	
		var xScale = d3.scaleLinear()
			.domain([0, 640])
			.range([0, 640 * scale_rate]);
		
		var yScale = d3.scaleLinear()
		.domain([0, 280])
		.range([0, 280 * scale_rate]);
	
		// エンティティ配列のデータ
		var dataset = [
			{'lineData':[[100,100],[200,100],[300,150]] ,'color':'green'},
			{'lineData':[[100,120],[200,120],[300,170]] ,'color':'green'},
			{'lineData':[[100,140],[200,140],[300,190]] ,'color':'green'},
			{'lineData':[[100,160],[200,50],[300,150]] ,'color':'rgba(0,0,255,0.5)'},
		];
		
	
		// SVGタグを作成する
		var svg = d3.select("#demo").append("svg");
		
		
		// 矢印を作成
		var marker = svg.append("defs").append("marker")
			.attr('id','arrowhead1')
			.attr('refX',1.5)
			.attr('refY',1.5)
			.attr('markerWidth',3)
			.attr('markerHeight',3)
			.attr('orient','auto')
			.append("path")
			.attr("d", "M 0 0 L 0 3 L 3 1.5 z")
			.attr("fill", "green")
			;
		
		
		  
		// SVGの幅を設定する
		svg.attr("width", xScale(640))
			.attr("height", yScale(280));
	
	
		// line変換関数: 線の配列をpathのd属性形式に変換する
		var lineArrToD = d3.line()
			.curve(d3.curveBasis)
			.x(function(d) {return xScale(d[0]);})
			.y(function(d) {return yScale(d[1]);});
		
		// 線(path)を追加する
		var line1 = svg.selectAll(".path1")
			.data(dataset)
			.enter()
			.append("path");
		
		// 線にデータを適用する
		line1
			.attr('d',function(d, i) {
				d = lineArrToD(d.lineData);
				return d;
			})
			.attr('stroke',function(d, i) {
				return d.color;
			})
			.attr('stroke-width',xScale(4))
			.attr('fill','none')
			.attr('marker-end',"url(#arrowhead1)")//線に矢印を付加
		;
			
			
	}
	

html


	<script src="d3/d3.min.js"></script>
	
	~
	
	<div id="demo"></div>	
	

SVGの出力