LoginSignup
3
7

More than 3 years have passed since last update.

【JavaScript】手軽に綺麗な「要素を矢印で繋いだグラフ」を描く方法(画像付き)

Posted at

概要

JavaScriptでグラフ(ノードとエッジの集合の方)を作りたい。
スクリーンショット 2020-02-10 16.42.15.png

JavaScriptでグラフを描画できるd3-graphvizの使い方や、色変更などできることを調査した。

基本の使い方

1.インストールする
簡単な方法はnpm install d3-graphviz(yarnでも可)
自分でビルドする場合は以下のコードを実行する。

$ git clone https://github.com/magjac/d3-graphviz.git
$ cd d3-graphviz
$ npm install
$ npm run build

また、unpkg.comを使うこともできる。その際、d3.jsviz.jsが必要であるためこれらも読み込む。

2.htmlファイルを作成する
必要なjsファイルを読み込み、グラフを描画する要素を用意する。
<script>タグ内にグラフ描画スクリプトを記述する。
renderDot()の引数に描画したいグラフを記述している。
最も簡単なデモのコードを以下に示す。このコードでは以下のようなグラフが描画される。

index.html
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/viz.js@1.8.1/viz.js" type="javascript/worker"></script>
<script src="https://unpkg.com/d3-graphviz@2.6.1/build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>

d3.select("#graph").graphviz()
    .fade(false)
    .renderDot('digraph  {a -> b}');

</script>

スクリーンショット 2020-01-21 13.03.11.png

以降、グラフ描画スクリプトのみ記述する。

ノードをカスタマイズする

何も指定せずにグラフを描画すると、上の画像のようなノードになる。

形を変更する

ノードの形を変えたい場合は、shapeを指定する。
グラフのすべてのノードに適用することも、特定のノードのみに適用することも可能。

d3.select("#graph").graphviz()
    .renderDot(`digraph  {
        node [shape="polygon"] // グラフのすべてのノードの形を変える場合
        a [shape="polygon"] // ノード「a」の形を変える場合
        a -> b
    }`);

スクリーンショット 2020-01-21 13.15.21.pngスクリーンショット 2020-01-21 13.15.42.png
d3-graphviz Shape Tweening Demoに様々な形の例がある。

背景の色・透明度を変更する

ノードの背景色や透明度を変更する場合はfillcolorを指定する。また、ノードにstyle="filled"を指定しておく(これを指定するとデフォルトのノード背景色はグレーになる)。
透明度は不透明度指定でRGBの後に記述する。ex. #FFFFFF80 // 半透明の白

d3.select("#graph").graphviz()
    .renderDot(`digraph  {
        node [style="filled" fillcolor="#FF000080"] // グラフのすべてのノードの背景色を変える場合
        a [fillcolor="#0000FF80"] // ノード「a」の背景色を変える場合
        b [fillcolor="#FFFF00"] // ノードごとに別の色にすることもできる
        a -> b
    }`);

スクリーンショット 2020-01-21 13.24.52.pngスクリーンショット 2020-01-21 13.25.27.pngスクリーンショット 2020-01-21 13.26.20.png

枠線の色・透明度・太さを変更する

ノードの枠線の色や透明度を変更する場合はcolorを指定する。透明度指定の方法は背景色と同じである。
また、枠線を太くする場合はstyle="bold"を指定する。

d3.select("#graph").graphviz()
    .renderDot(`digraph  {
        node [color="#FF000080" style="bold"] // グラフのすべてのノードの枠線の色・太さを変える場合。複数指定する場合はスペース区切りで記述する
        a [color="#0000FF80"] // ノード「a」の枠線の色を変える場合
        b [color="#FFFF00"] // ノードごとに別の色にすることもできる
        a -> b
    }`);

スクリーンショット 2020-01-21 13.33.43.pngスクリーンショット 2020-01-21 13.30.39.pngスクリーンショット 2020-01-21 13.30.52.png

文字の色・透明度・太さを変更する

透明度なしで文字色を変更する場合はfontcolorを指定する。透明度や太さを変更する場合は.attributer()で変更できる。

d3.select("#graph").graphviz()
    .attributer(function(d) { // 透明度・太さを変更する場合
        if (d.tag == "text") { // <text>タグ
            if (d.parent.attributes.id == "node-a") {
                d3.select(this).attr("font-weight", "bold") // 太字にする
            } else if (d.parent.attributes.id == "node-b") {
                d.attributes.fill = "#00000080" // 半透明の黒にする
            }
        }
    })
    .renderDot(`digraph  {
        node [fontcolor="#FF0000"] // 透明度を指定しない場合の文字色変更
        a [id="node-a"] // 要素のidを指定する
        b [id="node-b"]
        a -> b
    }`);

スクリーンショット 2020-01-21 13.38.52.pngスクリーンショット 2020-01-21 13.39.38.png

また、<ellipse>タグの時にfillに色を指定するとノードの色の変更もできる。

エッジをカスタマイズする

ノードと同様にエッジの色や太さを変更することもできる。
色・透明度の変更: colorを指定する。透明度指定はノードの場合と同じである。
太さの変更: style="bold"で太くできる。

d3.select("#graph").graphviz()
    .renderDot(`digraph  {
        a -> b [color="#FF000080"] // 色・透明度指定
        a -> c [style="bold"] // 太くする
    }`);

スクリーンショット 2020-01-21 13.44.53.png

その他

アニメーションさせる

d3-graphvizの機能でグラフをアニメーションをさせることもできる。
デモを参考にグラフを切り替えるコードを簡易的に記述したものを以下に示す。アニメーションさせたいグラフを配列で用意し、順番に描画している。
以下のコードではdelay等を指定していないため、点滅のようになる。

var dotIndex = 0;
var graphviz = d3.select("#graph").graphviz()
    .on("initEnd", render);

function render() {
    var dotLines = dots[dotIndex];
    var dot = dotLines.join('');
    graphviz
        .renderDot(dot)
        .on("end", function () {
            dotIndex = (dotIndex + 1) % dots.length;
            render();
        });
}

var dots = [
    [
        'digraph  {',
        '    a -> b',
        '}'
    ],
    [
        'digraph  {',
        '    a -> b [color="#FF0000"]',
        '}'
    ],
    [
        'digraph  {',
        '    a -> b [color="#0000FF"]',
        '}'
    ],
];

ログを出力する

.logEvents(true)でコンソールにログを出力することができる(デフォルトがtrue)。
d3-graphvizの各イベントについて、1つ前のイベントからの経過時間・スタートからの経過時間を知ることができる。

d3.select("#graph").graphviz()
    .logEvents(true)
    .renderDot('digraph  {a -> b}');

スクリーンショット 2020-02-10 15.03.15.png

まとめ

  • d3-graphvizを用いてJavaScriptで簡単にグラフを作成・表示できる。
  • ノード・エッジ共に簡単に色や透明度などを変更できる。
  • 複数のグラフをアニメーションで遷移させられることがわかった。
3
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
7