のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

d3.jsを使ってみる(4) SVGを利用して図形を描画する

皆さんこんにちは
お元気ですか。私はのんびりしています。

さて、遂にd3.jsを使って今回は図形を書いてみます。
なんかやっとそれっぽい感が出てきているような出てきていないような…。何やらSVGと呼ばれるものを利用するそうです。
そもそもSVGとは何なのか・・・

SVGとは?

Scalable Vector Graphicsの略です。
XMLベースの2Dベクター画像記述言語。2001年9月にW3C勧告として公開された。

ベクター画像は画像を点の集合体ではなく、線や面などの図形の集合体として扱うため、見る環境に応じて最適な表示が可能となる。

SVGとは 【 Scalable Vector Graphics 】 - 意味/解説/説明/定義 : IT用語辞典より

まぁ色々定義しているXMLのファイルから形式化したものか!?

図形を描写する

手順としては2つです。

  1. 領域を描写する
  2. 図形を描く

要は、紙用意して図形描くのと同じです。

例題

<head>
<meta charset = "utf-8">
</head>
<body>
	<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
	<script type="text/javascript">
		datasets = [30,40,50,60,80];
		var svg = d3.select("body").append("svg").attr({width:500,height:800});

		svg.selectAll("circle")
			.data(datasets)
			.enter()
			.append("circle")
			.attr({
				cx:function(d){return d},
				cy:function(d){return d},
				r:10,
				fill:"blue"
			});
	</script>
</body>

f:id:tereka:20140814162614p:plain

まず、領域の生成ですが、
var svg = d3.select("body").append("svg").attr({width:500,height:800});

attrで範囲を指定しています。

次の描画ですが、
今回は円を描くので、タグはcircleです。データセットに比べて要素数不足しているのでenter()そしてattrで細かいことを指定しています。
cx:横、cy:縦、r:半径、fill:色です。

因みにほかはどう描くのかといいますと

四角形

<script type="text/javascript">
datasets = [50,150,250,350,450];
var svg = d3.select("body").append("svg").attr({width:500,height:800});

svg.selectAll("rect")
	.data(datasets)
	.enter()
	.append("rect")
	.attr({
		x:function(d){return d},
		y:function(d){return 100},
		width:50,
		height:50,
		fill:"red"
	});
</script>

f:id:tereka:20140814163434p:plain

<script type="text/javascript">
svg.selectAll("line")
	.data(datasets)
	.enter()
	.append("line")
	.attr({
		x1:function(d){return d},
		y1:function(d){return 5},
		x2:function(d){return d},
		y2:function(d){return 100},
		"stroke-width":2,
		"stroke":"black"
	});
</script>

f:id:tereka:20140814163956p:plain

d3.jsを使ってみる(3) d3.dataをつかってタグにデータを適応する

皆さんこんにちは
お元気ですか。可視化って楽しいと思います。

三度目になって同じことを繰り返しますが…
いよいよd3っぽいことをしてみたいと思います

<head>
<meta charset = "utf-8">
</head>
<body>
	<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<script type="text/javascript">
	</script>
</body>
<script type="text/javascript">
        var datas = [12,36,108];
	var p = d3.select("body").selectAll("p");
	p.data(datas).text(function(d){
	return d
        });
</script>

f:id:tereka:20140814154106p:plain

気づいている人はいると思いますが、今回はpタグとdatasの長さが同じです。世の中こう都合よくはいきません。

p.dataに含まれるのは3つの種類があります。
update・・・普通に更新される内容
enter・・・追加が必要な内容
exit・・・必要がない

要はこの三種類それぞれについて対応する必要があります。

Update+Enter

<script type="text/javascript">
	var datas = [12,36,108,124];
	var p = d3.select("body").selectAll("p");
	update = p.data(datas)
	enter = update.enter()

	update.text(function(d){
		return d;
	})
	enter.append("p").text(function(d){
		return d;
	})
</script>

f:id:tereka:20140814155541p:plain

update地点では通常の更新を、enterではそもそもタグが不足しているので、まずは、タグを追加します。
その次にupdateと同じ挙動を行っています。

Update+Exit

<script type="text/javascript">
	var datas = [12,36];
	var p = d3.select("body").selectAll("p");
	update = p.data(datas)
	exit = update.exit()

	update.text(function(d){
		return d;
	})

	exit.remove()
</script>

f:id:tereka:20140814155757p:plain

updateでは同じ動作をしますが、exitについては必要がないのでremoveしています。

d3.jsを使ってみる(2) append,remove

皆さんこんにちは
お元気ですか。私は暑すぎてどうにかなりそう。

さて、今回はd3を使って要素の追加をしてみましょう。
今のところJQueryと大差ない使い方しているような・・・・まぁいいか

<head>
<meta charset = "utf-8">
</head>
<body>
	<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<script type="text/javascript">
	</script>
</body>

f:id:tereka:20140814145141p:plain

この中にあるscriptをいじっていきたいと思います。

append

appendを利用するとタグを追加することができます。

<script type="text/javascript">
	d3.select("body").append("p").text("あかさたな");
</script>

f:id:tereka:20140814152130p:plain

pタグで表示させる部分が一つ増えていますね。もちろん増やしたタグに対してtextやstyleを使ってCSSを適用させることができます。

remove

タグを削除する時に使います。

<script type="text/javascript">
	d3.select("body").remove("p");
</script>

f:id:tereka:20140814152605p:plain

もちろん、更地になります。

d3.jsを使ってみる(1) HTML,CSSの書き換え

皆さんこんにちは
お元気ですか。私は元気です。

さて、d3.jsについて解説したいと思います。

D3とは

Data-Driven-Document,Dが3つあってD3です。
何やらグラフやらチャートやら書けます。htmlやCSS,SVGと呼ばれるものをDOMよろしく編集することができます。
日本語版はこちら

実際に使ってみる

今回はd3を使ってDOMよろしくCSSやhtmlを動的に変化させたいと思います。

元のhtml

<head>
<meta charset = "utf-8">
</head>
<body>
	<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<p>あいうえお</p>
</body>

f:id:tereka:20140814145141p:plain

重要な部分はこの1文です。

これを読み込むことでd3を利用することができます。(ダウンロード版もあるのでそちらが必要な場合は公式から落としてきましょう)

テキストを変化させる

<head>
<meta charset = "utf-8">
</head>
<body>
	<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<p>あいうえお</p>
	<script type="text/javascript">
	   d3.select("body").selectAll("p").text("わをん");
	</script>
</body>

f:id:tereka:20140814145329p:plain
d3.selectでbodyを選択し、selectAllで全てのpを対象にする。.textでテキストを変更するような操作をしています。

これにCSSを追加してみましょう。

CSSの編集

script typeの部分を以下のスクリプトに置き換えましょう

<script type="text/javascript">
	   var p = d3.select("body").selectAll("p");
	   p.text("わをん")
	   	.style("font-size","50px")
	   	.style("color","red");
</script>

f:id:tereka:20140814145657p:plain
因みに中は無名関数とかも書けます。つまり、こんな形式もできるといった意味です。

.style("color",function(){
	   		return "blue";
	   	});

値の取得

alert(p.style("color"));

RGB形式で色の値を取得します。

次回はもう少し複雑なのを行おうかななんて思っています。

【ネタ】アッカーマン関数によるプログラミング言語最速決定戦?

皆さんこんにちは
おげんきですか?私はげんきです。

本日は最速決定戦やります。いやはやC++がはええええとかいいつつ
他の言語どうだっけなんて思う常日頃です。

エントリー

6つの言語で行いました
C++,Java,PHP,Python,Ruby,Javascript

種目

アッカーマン関数の計算
x = 3, y = 9 (以下を参照ください)
計測方法はtimeコマンドを用いた実行方法です。

※アッカーマン関数とは
{ \displaystyle
\begin{eqnarray*}
 &Ack&(0, y) = y + 1 \\
 &Ack&(x+1, 0) = Ack(x, 1) \\
 &Ack&(x + 1, y + 1) = Ack(x, Ack(x+1, y))
\end{eqnarray*}
}

で構成される再帰的な関数です。

判定方法

timeで計測しました。

ソースコード

C++

#include <iostream>
using namespace std;

int ack(int m,int n){
	if(m == 0) return n + 1;
	else if(n == 0) return ack(m-1,1);
	else return ack(m-1,ack(m,n-1));
}

int main(void){
	int a = ack(3,9);
	cout << a << endl;
}

Java

class Ack{
	private int ack(int m,int n){
		if(m == 0) return n + 1;
		else if(n == 0) return ack(m-1,1);
		else return ack(m-1,ack(m,n-1));
	}
	public static void main(String args[]){
		Ack ack = new Ack();
		System.out.println(ack.ack(3,9));
	}
}

PHP

<?php
function ack($m,$n){
	if($m == 0){
		return $n + 1;
	}else if($n == 0){
		return ack($m-1,1);
	}else{
		return ack($m-1,ack($m,$n-1));
	}
}

echo ack(3,9);
?>

Python

import sys

def ack(m,n):
	if m == 0:
		return n + 1
	elif n == 0:
		return ack(m-1,1)
	else:
		return ack(m-1,ack(m,n-1))

if __name__ == '__main__':
	sys.setrecursionlimit(10000)
	print ack(3,9)

Ruby

def ack(m,n)
	if m == 0 then
		return n + 1
	elsif n == 0 then
		return ack(m-1,1)
	else
		return ack(m-1,ack(m,n-1))
	end
end

puts ack(3,9)

Javascript

function ack(m,n){
	if(m == 0) return n + 1;
	else if(n == 0) return ack(m-1,1);
	else return ack(m-1,ack(m,n-1));
}

console.log(ack(3,9));

結果

言語 user sys total
C++ 0.01 0.00 0.01
Java 0.12 0.02 0.14
Php 1.67 0.12 1.79
Python 2.66 0.14 2.80
Ruby 0.91 0.25 1.22
javascript 0.11 0.01 0.12

感想

最適化したC++はやはり早かった。
Javaもやっぱり早いね、次に来るのがjavascriptというのには少し驚いた。
ウェブで使われに使われまくるだけあってえらく早い、スクリプト言語なのに。

僕の大好きなPythonくんが遅すぎて泣きそう。