JavaScriptで作った構成図エディタ GUI-DAC の紹介：GUIとDaC(Diagram as Code)の両方の特性を持つ俺の考えた最強の構成図エディターを目指して


![guidac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/1d4f5a38-488f-7532-915d-f6a60cf887ff.png)

## 理想の構成図エディタを作りたい

技術系のブログを書くときなど構成図をかくことがありますよね。
私の場合、構成図はパワポで作ることが多いのですが、もっといい感じに構成図を作りたいと常々思っていました。
パワポ以外の構成図エディタも試したのですが、なにか物足りなくてパワポに戻るを繰り返しています。でもパワポは私の理想の構成図エディタではありません。そこで、自分が理想とする構成図エディタを開発することにしました。

このブログで紹介する `GUI-DAC`(ジーユーアイ・ダック) は、私が開発中の構成図エディタです。これは、GUI[^1]とDaC[^2]の両方を特性を持つことで、私が期待する機能を全て実装することを目的に開発を進めています。

[^1]:GUI(Graphical User Interface)とは、アイコンやボタンなどを用いて直感的にわかりやすく操作できるようにしたユーザーインターフェースのこと。

[^2]:DaC(Diagram as Code)とは、コードを使用して図を作成および管理し、視覚的なドキュメントの作成、管理を改善する手法のこと。


## GUI-DaCのソース

プログラムソースはここにあります(2024年12月時点で未完成)
GUI-DaCの本体は `source/gui-dac.html` です。リポジトリのデータを全てダウンロードし、ブラウザで開くだけで使用できます。そのため、アプリのインストールは不要です（←こだわりポイントの１つ）。

https://github.com/zgw426/GUI-DAC.git

README.mdに使い方の詳細があります。

## デモ

GUI-DACで構成図を作成しているデモです。今ある構成図を一度削除し、新たに構成図を作成している様子です。画面左側の文字列が、構成図の情報のコード(文字列)です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/7LevCMjOvEk?si=-6-Y2vKLJ8GyJPIl" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


## GUI-DaCに盛り込んだ機能

盛り込みたい機能とその実装状況です。


### レイアウトの配置をカスタマイズしたい

DaC系のツールではアイコンなどレイアウトが自動配置のものが多い印象です。GUI-DaCは、DaC系のツールでありながらアイコンの配置場所をマウスで自由に移動できます。

<iframe width="560" height="315" src="https://www.youtube.com/embed/EgvBJb_R_XI?si=s1kHIqOPSENDNRVU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

### 突然使えなくなる事態はさけたい

GUI-DaCはソースを公開しています。
ソースファイルをコピーしておけばいつまでも使用できます。（今は未完成なので、完成した後のコピーをオススメします）

### アプリのインストールを不要にしたい

GUI-DACはアプリのインストールは不要です。
リポジトリのデータを全てダウンロードし、`source/gui-dac.html`ファイルをブラウザで開くだけで使用できます。そのため、アプリのインストールは不要です。

### 構成図の情報を外部に出したくない

GUI-DaCはローカル環境で動作します、サーバーは必要ありません。また、外部に情報を送る仕組みはありません。これはソースを見て頂ければわかると思います。

### 構成図をコード化したい(テキストファイル出力したい)

たとえばパワポで構成図を作成した場合、そのデータはバイナリ形式のファイルになります。GUI-DACは、構成図の情報をJSON形式の情報として管理しています。そのためテキストファイルとして出力できますし、そのテキストファイルを読み込むことで構成図を描画することができます。

以下動画の左側に表示される文字列が構成図の情報で、右側がその文字情報をもとに描画した構成図です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/_x4uE3hLgDE?si=trwAa4ZFGCE_ffLY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

### 学習コストを低くしたい

新しいアプリ・ツールを使うときは、使い方を覚える必要があります。
DaCツールでは、各パラメータに指定する値の規則などを理解する必要があります。この学習コストを削減するため、テンプレート機能を実装しました。

以下の赤破線の箇所にAWS用のテンプレートを表示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/1be1f782-bb24-0290-32af-7d118204dd59.png)

以下動画のように、テンプレートのアイコンをマウスでクリックすると構成図に追加できます。このテンプレートにより各パラメータの値を入力することなく構成図にオブジェクトを追加できるようになりました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/KHJqsO8jor8?si=XiZpt_JGyJvB2RxM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


### 構成図のプレビューをスムーズにしたい

DaCツールでは、構成図の情報を文字列として記載し、その結果をビジュアライズすることで構成図を確認できるものが多いです。
GUI-DaCは、文字列の修正による構成図の編集だけでなくGUIによる編集も可能にしたことで、比較的リアルタイムに構成図を描画します。

### サイズ変更や移動を楽にしたい

構成図を作成する際、オブジェクトの移動やサイズの変更は頻繁に行う作業です。これら作業をマウスで行えるようにすることで楽にしました。前述した"学習コストを低くしたい"のデモ動画を見てください。


### 共同開発をしたい

この機能は実装しませんでした。GUI-DaCは手軽に利用できることを目的としたためWebサーバ不要で使用できることを優先したことが実装しなかった理由です。ただし、構成図の情報はテキストファイルとして出力できるので、Git環境を用意いただければ共同開発はできると思います。



## GUI-DACの仕組み

GUI-DACがどのように構成図を作成・描画するかその仕組みを紹介します。

### オブジェクトという概念

GUI-DACでは、"アイコン"、"文字列"、枠の3つを1つのオブジェクトとして考えます。
以下は、VPCのオブジェクトの例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/34e3085f-a2c9-95c2-2846-6ed385243b33.png)

このVPCのオブジェクトには以下の要素をパラメータとして指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/e1080cbb-c2df-4a9e-2805-66cb51392409.png)

各パラメータを表にするとこのようになります。

||記載例|説明|
|---|---|---|
|1|  label        | 1つの構成図の中で一意の文字列|
|2|  ns           | 構成図に表示する文字列|
|3|  x            | X座標|
|4|  y            | Y座標|
|5|  w            | 幅|
|6|  h            | 高さ|
|7|  color        | 色|
|8|  opacity      | 透明度 0.6 なら60%|
|9|  group        | オブジェクトが所属するグループ|
|10| child-layers | 子要素になるグループ|
|16| child        | 自動グループ化により子要素になったグループ|
|17| line         | 線の色。NONEで線なし|
|18| imgTL        | 左上に配置する画像。NONEで指定なし|
|19| imgTR        | 右上に配置する画像。NONEで指定なし |
|20| imgBL        | 左下に配置する画像。NONEで指定なし|
|21| imgBR        | 左下に配置する画像。NONEで指定なし|
|22| imgCE        | 枠の中央に配置する画像。NONEで指定なし|
|23| imgCL        | 枠の左辺の中央に配置する画像。NONEで指定なし |
|24| imgCR        | 枠の右辺の中央に配置する画像。NONEで指定なし|
|25| imgCT        | 枠の上辺の中央に配置する画像。NONEで指定なし|
|26| imgCB        | 枠の底辺の中央に配置する画像。NONEで指定なし |
|27| imgSize      | 配置する画像の倍率。2 なら2倍|
|28| txtPosition  | 文字列 ns の表示位置。txtTLは左上。txtCEは中央|
|29| transFlg     | ON:大きさ(w,h)変更可、OFF:大きさ(w,h)固定|


さきほどのオブジェクトVPCのコードはこのようになります。

```json:オブジェクトVPCのコードサンプル
    {
      "label": "VPC01",
      "ns": "Virtual private cloud (VPC)",
      "x": 1010,
      "y": 230,
      "w": 630,
      "h": 700,
      "color": "none",
      "opacity": "1.0",
      "group": "gr102",
      "child-layers": [
        "gr103",
        "gr104",
        "gr105"
      ],
      "child": [],
      "line": "#8C4FFF",
      "imgTL": "vpc.png",
      "imgTR": "NONE",
      "imgBL": "NONE",
      "imgBR": "NONE",
      "imgCE": "NONE",
      "imgCL": "NONE",
      "imgCR": "NONE",
      "imgCT": "NONE",
      "imgCB": "NONE",
      "imgSize": 1,
      "txtPosition": "txtTL",
      "transFlg": "ON"
    }
```



### サイズ変更や移動の仕組みについて

GUI-DACは、移動・サイズ変更をスムーズにできるようオブジェクト・自動グループ・レイヤーの概念があります。

- オブジェクトにより移動する"アイコン","枠","文字"を1つの塊として移動、サイズ変更します
- 自動グループにより、複数のオブジェクトを自動的に1つの塊として判定し、まとめて移動します
- レイヤーにより、VPC①とVPC②といった重なる必要のないオブジェクトの重なりを防止します

#### オブジェクトについて

オブジェクトについては、前述の"オブジェクトという概念"でパラメータなどを説明しています。ここは補足説明です。

GUI-DaCは、"アイコン"、"枠"、"文字"の3要素を最小単位の塊としています。
移動やサイズ変更はそのオブジェクト単位で行います。オブジェクトの概念により、アイコンと枠がずれたりすることなく移動やサイズ変更ができます。

以下の場合、VPCのアイコン、文字列 "Virtual private cloud (VPC)"、枠の3つが1つのオブジェクトになっています。このオブジェクトが移動の最小単位になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/34e3085f-a2c9-95c2-2846-6ed385243b33.png)

以下の左側のように枠をかきたくない場合は枠を透明にします。つまり、見た目には枠がないですが実際には右側の破線のように枠があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/859a124a-410a-61b8-bc4e-3fd91c18fcbe.png)


#### 自動グループについて

自動グループとは、オブジェクトの重なりにより1つのグループとするか判定する仕組みです。自動グループによってグループ化されたものは、まとめて移動することができます。

たとえば以下図は、サブネットワークとEC2の構成図です。これらは重なっていないため自動グループ化によるグループ化はしません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/9d0736df-b2df-1a26-6144-261d1fd5e136.png)

以下図では、サブネットワークの中にEC2があります。この場合、自動グループ化によって1つのグループとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/38cee86f-6c67-4427-a187-a24c77276107.png)

自動グループによって1つのグループとなった状態で、サブネットワークをマウスドラッグで移動すると、中のEC2も一緒に移動します。また、EC2をマウスドラッグで移動すると、サブネットワークは移動せずEC2だけが移動します。

以下は自動グループのデモです。オブジェクトを重ねることでグループ化され、まとめて移動できていることがわかります。

<iframe width="560" height="315" src="https://www.youtube.com/embed/LSRW2hXTKcs?si=Winu_um7-bBrm9fW" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


#### レイヤーについて

レイヤーという階層のような概念により、複数オブジェクトの重なりを防止したり許容したりします。

以下動画は、オブジェクトの重なり制御の例です。重ならないオブジェクト同士が近づくと、押し出すようにオブジェクトが移動します。

<iframe width="560" height="315" src="https://www.youtube.com/embed/yYh6y8n4dNg?si=g2gi2iw-A-73LGaf" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


#### 自動グループとレイヤーによるオブジェクトの制御

以下は前述した自動グループとレイヤーがあるとAWS構成図をどのように作成できるかを紹介したデモ動画です。構成図を作成する際に、アイコンや文字がまとめて移動していたり、重ねたくないオブジェクトが重ならないようなっています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/LSRW2hXTKcs?si=eOjMJkooa6v2WfV6" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


#### 接続線について

構成図では、通信経路や処理の流れなどを線で表現することがあります。GUI-DACでは、複数のオブジェクトを線でつなぐ接続線の機能があります。この接続線はオブジェクトの移動に追随します。この追随により、構成図の編集作業を楽にします。

<iframe width="560" height="315" src="https://www.youtube.com/embed/qd2CwMx6qfc?si=fmHMopU6lQ8kHSTF" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

以下はGUI-DACの接続線のサンプルです。雲のアイコンをマウスでドラッグしてみてください、→(矢印)が追随します。

<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="vYqZJRd" data-pen-title="gui-dac-矢印" data-user="sosi-now" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sosi-now/pen/vYqZJRd">
  gui-dac-矢印</a> by suo (<a href="https://codepen.io/sosi-now">@sosi-now</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

余談ですが、マウスドラッグで雲のアイコンを重ねようとしても重なりません。これは前述した重なり防止機能によるものです。



## 今開発してること

GUI-DACは、まだまだ開発中。直近で取り組んでいることを紹介します。

### 接続線の編集を楽にしたい

接続線とは構成図で表す通信経路のことです。接続線の新規作成が楽になるようにマウス操作で行えるよう開発中です。

## さいごに

休み休みで作っているので進捗悪いですが、のんびり作っていきます。いいねを頂けると頑張るモチベーションが上がると思いますので、みなさんのあたたかい **いいね** お待ちしています。