YSCJP.com

シーケンス図を描く

『図を書け図を!』で紹介した、HTMLとSVGでシーケンス図を作成するためのライブラリです。

本格的なUMLのシーケンス図に対応しているわけではありませんが、処理の簡単な流れを記述する程度であれば、それなりに使える内容です。

作った本人が言うのも何ですが、意外と便利なので自分でも使い方を忘れてしまわない様に、公開します。

シーケンス図を書く

まずは、簡単な例とそのソースです。

シーケンス作成スクリプト

1行目は、おまじないです。

内部でbody要素にアクセスするので、body要素が存在するタイミングで、必ず1回呼び出す必要があります。

windowloadイベント(DOMContentLoadedイベントでも可)で、呼び出されることを想定しています。

複数回呼び出された場合、2回目以降の呼び出しは無視します。

3行目は、シーケンス図作成マネージャのインスタンスの生成です。引数は、シーケンス図を表示する要素のIDです。ライフラインはこのマネージャで作成します。

4行目から6行目で、マネージャによりライフラインを作成しています。第一引数はライフラインの名前で、ライフライン要素のクラスとして設定されます。第ニ引数はライフラインの表示名です。第三引数はUMLを意識したクラス名で、表示名の後ろに:で連結して表示されます。省略した場合は何も表示しません。

7行目で、4行目で作成したライフラインに、シーケンスの起点となるアクティベーションを作成します。

第一引数はアクティベーションの開始位置で、ライフライン上部のBox底面からの距離をem単位で指定します。開始位置を省略した場合は、1emとなります。

8行目で、7行目で作成したアクティベーションから、クラスBのインスタンスを作成するメッセージを送信します。

第一引数は送信先のライフラインです。第二引数と第三引数はそれぞれ、リクエストメッセージとレスポンスメッセージの説明文です。

戻り値は、送信先のアクティベーションです。

9行目で、8行目のメッセージの戻り値のアクティベーションから、クラスCに通常の同期メッセージを送信します。

第一から第三引数は、8行目のcreateMessageと同じです。

第四引数は、呼び出し先アクティベーションの開始位置で、呼び出し元アクティベーションの上端からの距離を、デフォルトとのオフセットでem単位で指定します。開始位置を省略した場合は、0.5emとなります。上記例では、0.5em2emを加算して3.5emとしています。

メッセージの開始位置は、条件によって異なるので、オフセットという形で指定します。

10行目は、処理に関する説明文をアクティベーションに対して追加します。

引数は説明文です。

11行目も説明文の追加ですが、説明文を複数行とする場合は、<br>で分割します。

12行目もおまじないです。ライフラインの長さを調整します。シーケンス図の記述の最後に、必ず呼び出してください。

機能の詳細

実は、先程の紹介で殆ど全ての機能を網羅しているのですが、少しだけ抜けているので解説します。

(1)一方メッセージ

一方メッセージ

6行目のoneWayMessageSが、一方メッセージの作成です。

(2)同期メッセージのアクティベーションの高さ

まずは、デフォルト。

メッセージの説明が長い場合、折り返したい場合があります。

そのような場合は、メッセージの開始位置や、送信先のアクティベーションのサイズを調整する必要があります。

アクティベーションのサイズ調整

7行目の、messageメソッドの第四引数がリクエストメッセージの位置指定のオフセットで、第五引数が送信先アクティベーションのサイズになります。共にem単位で指定します。

上記例では、リクエストメッセージの開始位置を、デフォルトの0.5em3em加算して3.5emとし、送信先アクティベーションのサイズを、デフォルトの2emから4emに変更しています。

(3)メモの表示位置調整

普通にメモを付与すると、以下のようになります。

何らかの理由で、位置を調整したい場合は、オフセットを指定することが出来ます。

アクティベーションのサイズ調整

7行目で、「クラスBにメモ」を、デフォルトの0.5em1em加算して、アクティベーションのtopから、1.5emの位置に表示しています。

8行目で、「クラスAにメモ」を、デフォルトの0.5em3em加算して、直前のレスポンスメッセージから、3.5emの位置に表示しています。

(4)複雑な一方メッセージ

イベント制御などで、複雑な一方メッセージによるシーケンス図を描く時に、標準のままでは不都合な場合があります。

まずは、下記シーケンスを見てください。

デフォルトの一方指示で、複雑な一方メッセージ

デフォルトでは、一方メッセージも同期メッセージと同じように、呼び出し先のアクティベートのサイズに合わせて、呼び出し元のアクティベートのサイズを変更します。

このため、本来は分離させたいクラスBのアクティベーションが、くっついた状態になってしまいます。

そこで、呼び出し元のアクティベートを変更しない指示で、一方メッセージを表示します。

再描画しない指示で、複雑な一方メッセージ

8行目と9行目が、呼び出し元のアクティベートを変更しない一方メッセージです。

8行目では、送信先アクティベートのサイズを、第四引数で3emに変更しています。第三引数には、デフォルトのままである0を指定します。

9行目では、デフォルトより2.5em下から、一方メッセージを出力しています。

シーケンス図をカスタマイズする

シーケンス図の表示内容は、基本的に全てCSSで指定されているので、これを上書きすることで変更することが出来ます。

クラスAのライフラインには'lifeA'を、クラスBのライフラインには'lifeB'を、それぞれの名前としています。

シーケンス図を表示する起点となっている要素のIDは、seq07です。

カスタマイズ用のCSS

シーケンス図のカスタマイズで、他の図に影響を与えたくない場合は、CSSのセレクタを起点となる要素のIDから始めるようにします。この例では、#seq07です。

1行目は、このシーケンス図にある全てのライフラインのタイトル部分を選択します。背景色を水色に変更しています。

2行目は、このシーケンス図にある全てのアクティビティを選択します。背景色を灰色に変更しています。

3行目は、このシーケンス図にあるlifeBというクラス名のライフラインの、全てのメモを選択します。前景色を赤色に変更しています。

10行目と13行目は、メッセージのタイトルを選択しています。メッセージのタイトルやメモには、それぞれユニークなIDが自動的に付与されるので、それを利用することで個別にスタイルを変更できます。

命名規則は、以下のとおりです。

(a)_(b)_active(c)_(d)_(e)

  (a) 起点となる要素のID。new SDManager('xxxx')で渡している、'xxxx'
  (b) ライフラインの名前
  (c) ライフライン上の、アクティビティの番号。01から始まる連番
  (d) アクティビティ上のメッセージの番号。1から始まる連番
  (e) リクエストメッセージ:reqMsg
      レスポンスメッセージ:resMsg
      メモ:memo

13行目で、(d)が3となっているのは、メモもメッセージと同様に管理されているためです。1つめのメッセージが1、メモが2、2つ目のメッセージが3となります。

注意点

フォントサイズ

シーケンス図が影響を受ける範囲のフォントサイズを変更する場合、起点となる要素かその先祖に指定してください。起点となる要素の子孫に指定すると、表示が崩れます。

センタリング

絶対配置で要素を配置している関係上、正確にセンタリングを行うことは出来ません。

また、CSSのdisplay: flex;margin: auto;等でセンタリング指示を行うと、表示が崩れます。

しかし、図をセンタに表示したいという要望は多いと思われるので、いくつかの解決策を紹介します。

(1)パディングを指定する

起点となる要素の左側のパディングを、図がセンタリングされているように見える程度に設定します。

パディングでセンタリングさせるCSS
パディングでシーケンス図をセンタリング

上記のシーケンス図のように、左右対称ではないケースでは、数字だけで正確にセンタリングするよりも、人の目でセンタリングされているように見える位置に調整したほうが、心地よく見えることもあります。

但し、幅が固定ではないコンテンツでは、意味がありません。

(2)レンダリング後にdisplay: flex;を設定する

CSSのセンタリング指示で表示が崩れるのは、SVGのレンダリング前にセンタリングの指示がHTML要素にのみ反映されるせいだと思われるので、レンダリング後にJavaScriptで設定します、

レンダリング後にdisplay: flex;を設定するScript
レンダリング後にdisplay: flex;でセンタリング

この方法では、センタリングされるのはあくまでもライフラインのみなので、長いメモがライフラインの外にはみ出している様なケースでは、不自然な表示となりますが、左右の幅が可変のコンテンツでも、追随してくれるという利点があります。

(3)レンダリング後にwidthとmarginを設定する

widthmarginを、レンダリング後にJavaScriptで設定します、

レンダリング後にwidthとmarginを設定するScript
レンダリング後にwidthとmarginでセンタリング

正確にシーケンス図の横幅を取得する方法がないので、あくまでも見た目重視で設定します(トライ・アンド・エラー※ってやつです。)。左右の幅が可変のコンテンツでも、追随してくれます。


※正確にはトライアル・アンド・エラーだそうです。