PlantUMLのシーケンス図を無理やりヘッダー固定スクロールできるようにしてみました
IoT事業部の熊膳です。
設計時にシーケン図を使うことが多くあります。このときPlantUMLを使うことが多いです。コードはGitHubで管理しCIでシーケンス図の画像作成というパターンです。このPlantUMLを使ったシーケンス図はとても便利なのですが、長いと途中で何がどれかわからなくなることありますよね。それに対応してみたいと思います。
困っていること
IoT案件の場合のシーケンス図は、登場人物が多いことがよくあります。デバイス、AWS IoT、DynamoDB、S3、認証局周りなどなどいろいろあります。このとき、オンライン会議でシーケンス図の共有時やレビュー時に困ったことが起きてます。
シーケンスが長い場合に、誰から誰へのメッセージなのかがわかりにくいという問題です(長いのが問題というのは今回は無視)。結局「すみません、右から2番目ってなんでした?」や「一回上まで見せていただけないですか?」という本質ではないやり取りが行われることになってしまいます。コードのままであればツールの画面分割機能でなんとか出来なくもないのですが、画像だとやりにくいです。
改善してみた
なんとか頑張って、オブジェクト部分を固定にして残りをスクロールできるようにしてみました。どうでしょうか、いい感じですよね。
制限あったり、微妙なところもあるのですが、1つのアイデアとして方法を共有します。
作戦
作戦はこうです。
- シーケンス画像を複製する(同じ画像を上下2枚並べます)
- 上の画像をオブジェクト部分(ヘッダー)のみ表示し上部に固定領域とする
- 下の画像をオブジェクト部分を削除し、スクロール可能領域とする
私は簡単なJavaScriptやCSSをいじることしか出来ないため、ブラウザ(Chrome)で表示する作戦で行います。なので、これ以降のコードは、ChomeのDevtoolsのConsoleでの作業となります。
環境は以下です。
- macOS Big Sur(11.5.2)
- Chrome 92(92.0.4515.159)
また、実験用にシーケンス図を用意しました。
シーケンス画像を複製する
まずはPlantUMLのシーケンス図のみをChromeで表示します。上記のサンプルを使うか、画像を右クリックして「新しいタブで画像を開く」が簡単です。もちろんファイルを直接開いてもらってもいいです。とにかく画像のみ表示します。 画像が少し小さいので拡大するためにマウスで画像をクリックします(そもそも小さいサイズはスクロールしないですし)。以降は拡大したサイズを前提に進めます。
今回はじめて知ったのですが、Chromeでタブに画像を表示すると、対象の画像をimg
タグで指定したHTMLになるようです。
<html style="height: 100%;"> <head> <meta name="viewport" content="width=device-width, minimum-scale=0.1"> <title>PlantUML image</title> </head> <body style="margin: 0px; background: #0e0e0e; height: 100%"> <img style="-webkit-user-select: none;margin: auto;cursor: zoom-out;background-color: hsl(0, 0%, 90%);transition: background-color 300ms;" src="PlantUML image url" width="640" height="1378"> </body> </html>
このimg
タグを複製します。Consoleで以下を入力します。
const img = document.getElementsByTagName('img'); document.body.appendChild(img[0].cloneNode(false));
やってることは、img
タグを見つけてそれをbody
タグ配下にコピーする、です。これで複製できました。
上の画像をオブジェクト部分のみ表示し上部に固定領域とする
続いて、ヘッダー固定部分です。オブジェクト部分のみ固定したいので、上の画像に対して以下を行います。
- オブジェクト部分のサイズを特定
- CSSでサイズを指定し切り抜く
- CSSで上部に固定
オブジェクト部分のサイズを特定します。この部分がこの作戦の未熟な部分でコード化できてない部分です。何らかの方法で固定したい部分の高さを計測してください。表示してから後から調整でも問題ないです。私が測定したところ、(上部の方法で拡大した場合)シーケンス図にタイトルがない場合は100px、タイトルありの場合は、128pxや148pxぐらいがいい感じでした。
Consoleで以下を入力します。
const header = 100; // タイトルがある場合は128や148など const realHeight = img[0].height; // 表示上の高さを保持(後で使うため) img[0].style.cssText = img[0].style.cssText+`object-fit:cover;object-position:top;height:${header}px;position:sticky;top:0`; document.getElementsByTagName('body')[0].style.height = '';
上の画像(img[0])に新しいstyleを追加してます。
- 切り抜く部分を指定(ヘッダー部のみ表示)
- object-fit:cover, object-position:top, top, height:100px
- 上部固定
- position:sticky, top:0
また、position:sticky
は、親要素の指定によって期待通りに動作しない場合があるため、body
タグの高さの指定を削除します。
- heightを削除
- style.height = ''
下の画像をオブジェクト部分を削除し、スクロール可能領域とする
続いて、下の画像からオブジェクト部分(ヘッダー部)を削除します。こちらは固定指定せずスクロールさせます。
Consoleで以下を入力します。
img[1].style.cssText = img[1].style.cssText+`object-fit:cover;object-position:bottom;height:${realHeight - header}px`;
下の画像(img[1])に新しいstyleを追加してます。
- 切り抜く部分を指定
- object-fit:cover, object-position:bottom, height:オブジェクト部分を引いたサイズpx
これで完成です。
既知の問題点
わかってる課題もあります。対応できるものもありますが、理解していればそれほど問題でもないのかなと思ってます。
- ブラウザをリサイズしたら画像が再読み込みになるので指定したスタイルが外れる。
- 上の画像をクリックすると画像のサイズが変更され意図した表示にならない。
まとめ
以下を行うことでPlantUMLのシーケンス図をいい感じで表示できました。
- PlantUML シーケンス図を表示する。
- 画像をクリックして拡大する。
- ChromeのDevToolsのConsoleで以下を入力する。
const header = 100; // タイトルがある場合は128や148など const img = document.getElementsByTagName('img'); const realHeight = img[0].height; // 表示上の高さを保持(後で使うため) document.body.appendChild(img[0].cloneNode(false)); img[0].style.cssText = img[0].style.cssText+`object-fit:cover;object-position:top;height:${header}px;position:sticky;top:0`; document.getElementsByTagName('body')[0].style.height = ''; img[1].style.cssText = img[1].style.cssText+`object-fit:cover;object-position:bottom;height:${realHeight - header}px`;
かなり無理矢理ですが、シーケンス図のヘッダー固定が実現できました。誰でも簡単にってわけにはいきませんが、便利に使えるかもしれませんね。
PlantUMLのシーケンス図をいい感じに表示する方法を紹介しました。
以上、どなたかの参考になれば幸いです。
おまけ
自分用にChrome機能拡張にしてみました。制限事項やたまに変な動作することありますが、同じ問題を抱えてる方に使っていただければと思います。
使い方は、機能拡張をインストールし、シーケンス図の画像をタブで開いてから画像を右クリックです。
ネット上ではなくローカルPC上のファイルでこの機能を利用する場合は、Chrome機能拡張画面のPlantUML Image Viewerの詳細ボタンをクリックし、「ファイルの URL へのアクセスを許可する」をONにしてください。