D3.js サンプル orgoShmorgo を読んでソーシャルグラフを考えるの巻き – その四

Pocket

spyseeみたいな人物相関図をつくりたいということで始まった D3.js サンプル orgoShmorgo の勉強でしたが、中心的な処理内容はだいたい把握できました。
ですので、今回はエントリーポイント(プログラムの開始)からの処理遷移をざっくり確認して復習します。次回はいよいよ人物相関図の作成に入りたいと思います。

と、ここで、とても重要な事を見つけてしまいました!!!

同様のサンプルでもっとシンプルなものがあった!!

http://bl.ocks.org/mbostock/3037015

なんちゅうこった。こっちで学習した方が早いやんけ!!

マジかよ。ちゃんと、ページを読むべきだったなぁ。。

あと、以下のようなLabeled Force Layoutというのも見つけました。
人物相関図ではやはりプロフィール画像が必要なので、image要素の扱い方も知っておく必要がありました。

labeledforcelayout

エントリーポイントは、たぶんここ – d3.js サンプル


	$.getJSON("molecules.json", function(json) {
		moleculeExamples = json;
		newMoleculeSimulation (moleculeExamples, '2-amino-propanoic_acid');
	});

これですね。これ。
最初は全く気づいていなかったのですが、以下のようなmolecules.jsonというファイルがありまして、atomDBとは別に、各分子モデルの定義が書かれていたんですねー。いやはや。


{
    "2-amino-propanoic_acid": {
          "nodes": [
            {"symbol": "C", "size": 12, "bonds": 1, "id":1},
            {"symbol": "C", "size": 12, "bonds": 3, "id":2},
            {"symbol": "C", "size": 12, "bonds": 4, "id":3},
            {"symbol": "N", "size": 14, "bonds": 1, "id":4},
            {"symbol": "H", "size": 1, "bonds": 1, "id":5},
            {"symbol": "O", "size": 16, "bonds": 2, "id":6},
            {"symbol": "O", "size": 16, "bonds": 1, "id":7},

で、あとは処理遷移をざっと書くと、

  1. $.getJSON(“molecules.json” で、molecules.jsonを呼び出し
  2. newMoleculeSimulation (moleculeExamples, ‘2-amino-propanoic_acid’) をcall
    1. svg領域の作成
    2. orgoShmorgo(newMolecule) をcall
      1. buildMolecule() をcall
        1. svg.selectAll(“.link”) 要素をlinkに代入(デフォルトは空)
        2. jsonで呼び出したlinklistをlink.data()でupdate
        3. link内の内容に応じて、<g class=”link”><line /></g>を生成
        4. link.exit().remove();
        5. svg.selectAll(“.noge”) 要素をnogeに代入(デフォルトは空)
        6. jsonで呼び出したnodelistをlink.data()でupdate
        7. node内の内容に応じて、<g class=”node”><circle /><text /></g>を生成
        8. node.exit().remove();
        9. force.start(); !!!! YES!!

 

ということになっております。

なんだよ大したことねーじゃねーか!!という感じですが、未だに細かいところは不明だったりもします。

ついでに、Labeled Force Layout – d3.js サンプル


var width = 960,
    height = 500

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var force = d3.layout.force()
    .gravity(.05)
    .distance(100)
    .charge(-100)
    .size([width, height]);

d3.json("graph.json", function(error, json) {
  if (error) throw error;

  force
      .nodes(json.nodes)
      .links(json.links)
      .start();

  var link = svg.selectAll(".link")
      .data(json.links)
    .enter().append("line")
      .attr("class", "link");

  var node = svg.selectAll(".node")
      .data(json.nodes)
    .enter().append("g")
      .attr("class", "node")
      .call(force.drag);

  node.append("image")
      .attr("xlink:href", "https://github.com/favicon.ico")
      .attr("x", -8)
      .attr("y", -8)
      .attr("width", 16)
      .attr("height", 16);

  node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.name });

  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  });
});

動的に要素を入れ替えたりしないので記述がシンプルですね。
というか、シンプルにjsonを読み込むメソッドがあるんですね。

d3.json("graph.json", function(error, json) {

そしてimageはこんな感じにgの子要素としてあげればいいと。

  node.append("image")
      .attr("xlink:href", "https://github.com/favicon.ico")
      .attr("x", -8)
      .attr("y", -8)
      .attr("width", 16)
      .attr("height", 16);

ふむふむ。簡単だ。

  node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.name });

まぁ、テキストも、確かに。うん。なんかやれそうな気がする。

じゃぁ、カスタマイズいっちゃおうかということで、見よう見まねでforeignObject要素を追加してxhtmlを書いてみます。

foreignObject要素を追加してxhtmlを記述するサンプル


  node.append("foreignObject")
      .attr("x", 10)
      .attr("y", 10)
      .attr("width", 150)
      .attr("height", 150)
      .each(function(d) {
        // Add node div
        d3.select(this)
            .append("xhtml:div")
            .attr("style", "font-family:verdana;")
            .text("xhtml内のテキストは折り返せる")
            .append("input")
            .attr("type", "button")
            .attr("value", "form要素もOK Let's Click")
            .attr("onClick", "alert('alert')");
        });

ポイントなのは、foreignObject直下のdiv要素はxhtml定義になるのですが、その際、名前空間付きの表記”xhtml:div”にしてやらないと、domとしては構築されても表示されないので注意が必要です。
こんな感じになりました。

foreignobject

かなりわかってきたので、次回はいよいよ、とりあえずの人物相関図を完成させたいと思います。

Pocket