ネットワーク型（ノード型、二分木型、ツリー型）のデータをブラウザで描画する (vis.js)

# 概要

vis.js Network というライブラリを使うときれいに表示できます。

# 本家サイト

https://visjs.org/

https://visjs.github.io/vis-network/docs/network/



## ライセンス

Apache-2.0, MIT license

https://github.com/visjs/vis-network/blob/master/LICENSE-APACHE-2.0

https://github.com/visjs/vis-network/blob/master/LICENSE-MIT

## 例

公式の例がとても充実しております。

https://visjs.github.io/vis-network/examples/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/2f31a762-2c7e-6f37-04c1-708b08ef575b.png)




# 利用方法

## ライブラリの読み込み

```html
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
 ```

## データの定義

ノードに相当するデータと、ノードを連結するエッジのそれぞれを配列で定義します。

自分で定義したオブジェクトをバインドすることも可能です。

```javascript
var nodesArray = [
    {id: 1, label: 'Node 1', obj:{comment:"自分で定義したObject"}}, // 自分で使うオブジェクトをバインドしてよい
    {id: 2, label: 'Node 2'},
    {id: 3, label: 'Node 3'},
    {id: 4, label: 'Node 4'},
    {id: 5, label: 'Node 5'}
];

var edgesArray = [
    {from: 1, to: 2, label:"1 -> 2", width:1 }, // *from, *to, *label, 太さを指定できる
    {from: 1, to: 3},
    {from: 3, to: 4},
    {from: 3, to: 5}
];
```

## データの表示

表示部分に表示したい領域を定義しておきます。

```html
<div id="mynetwork"></div>
```

データを割り当てて表示します。

```javascript
// create an array with nodes ノードの定義
var nodes = new vis.DataSet(nodesArray);
// create an array with edges エッジの定義
var edges = new vis.DataSet(edgesArray);
// create a network ネットワークを表示する領域
var container = document.getElementById('mynetwork');
// provide the data in the vis format 表示するデータの構築
var data = {
    nodes: nodes,
    edges: edges
};
// var options = {}; // オプションを空にするとすべてデフォルトで設定される
var options = {layout:{
	hierarchical:{
		direction:"UD",
		sortMethod:"directed" // default is "hubsize"
	},
}};
// initialize your network! 初期化
var network = new vis.Network(container, data, options);
```

## 結果

このようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/cd52b053-61aa-583a-96c1-9b527c9320dd.png)

表示オプションを何も指定しないと、このようにユルっとした表示になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/25941817-a0d2-6739-3f54-cd1d4aba9e3b.png)

## ノードをクリックしたときのイベントを定義したい

以下のようにすると、クリックされたノードの情報がパラメータとして渡されます

```javascript
network.on("click", function(params) {
    // params がクリックされたノードの情報。初期化オプションにより複数ノードの選択も可能。
  });
```



「ノードがクリックされたときに、そのノードに新しいノードを追加する」としたいときは以下のようにします。

ノード番号の最大値が maxid に入っているとします。

```javascript
network.on("click", function(params) {
    if (params.nodes.length == 1) {
      var nodeId = params.nodes[0];
      var node = nodes.get(nodeId);
      console.log(node);
      console.log(node.label + 'がクリックされました');
      
      maxid++;
      // 指定されたノードに新しいノードを追加する
      var o = {id: maxid, label: 'Node ' + maxid};
      nodesArray.push(o);
      var e = {from:nodeId,to:maxid};
      edgesArray.push(e);
      // network.body.data.edges.add([{from: from_id, to: to_id}])
      nodes.update(nodesArray);
      edges.update(edgesArray);
    }
  });
```

# サンプル全体

vis.js に jQuery と bootstrap も混ぜてあります。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>vis.js-example</title>
<!-- jQuery 3.5.1 -->
<script src="https://code.jquery.com/jquery-3.5.1.js"
	integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
	crossorigin="anonymous"></script>
<!-- bootstrap 5 -->
<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
	rel="stylesheet"
	integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
	crossorigin="anonymous">

<!-- vis.js https://github.com/visjs/vis-network -->
<!-- Apache-2.0, MIT license -->
<!-- https://github.com/visjs/vis-network/blob/master/LICENSE-APACHE-2.0 -->
<!-- https://github.com/visjs/vis-network/blob/master/LICENSE-MIT -->
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
 
<script type="text/javascript" class="init">

var nodesArray = [
    {id: 1, label: 'Node 1', obj:{comment:"自分で定義したObject"}}, // 自分で使うオブジェクトをバインドしてよい
    {id: 2, label: 'Node 2'},
    {id: 3, label: 'Node 3'},
    {id: 4, label: 'Node 4'},
    {id: 5, label: 'Node 5'}
];

var edgesArray = [
    {from: 1, to: 2, label:"1 -> 2", width:1 }, // *from, *to, *label, 太さを指定できる
    {from: 1, to: 3},
    {from: 3, to: 4},
    {from: 3, to: 5}
];

var maxid = nodesArray.length;

function init(){
	
    // create an array with nodes ノードの定義
    var nodes = new vis.DataSet(nodesArray);
    // create an array with edges エッジの定義
    var edges = new vis.DataSet(edgesArray);
    // create a network ネットワークを表示する領域
    var container = document.getElementById('mynetwork');
    // provide the data in the vis format 表示するデータの構築
    var data = {
        nodes: nodes,
        edges: edges
    };
    // var options = {}; // オプションを空にするとすべてデフォルトで設定される
    var options = {layout:{
    	hierarchical:{
    		direction:"UD",
    		sortMethod:"directed" // default is "hubsize"
    	},
    }};
    // initialize your network! 初期化
    var network = new vis.Network(container, data, options);
        // event イベントの定義
    network.on("click", function(params) {
        if (params.nodes.length == 1) {
          var nodeId = params.nodes[0];
          var node = nodes.get(nodeId);
          console.log(node);
          console.log(node.label + 'がクリックされました');
          
          maxid++;
          // 指定されたノードに新しいノードを追加する
          var o = {id: maxid, label: 'Node ' + maxid};
          nodesArray.push(o);
          var e = {from:nodeId,to:maxid};
          edgesArray.push(e);
          // network.body.data.edges.add([{from: from_id, to: to_id}])
          nodes.update(nodesArray);
          edges.update(edgesArray);
        }
      });
}

$(document).ready(function() {
	init();
} // end of function
); // end of .ready
</script>

<style type="text/css">
    #mynetwork {
        width: 600px;
        height: 400px;
        border: 1px solid lightgray;
    }
</style>

</head>
<body class="m-3">
	<div class="row">
		<div class="col-12">
			<div id="mynetwork"></div>
		</div>
	</div>
</body>
</html>
```


以上です。