實現UML 序列圖 -- csdn MarkDown 第六篇 技術篇

這一篇開始討論代碼層面的問題。主要是markdown的功能的設計實現。

這一篇先從markdown外圍的代碼開始講起:
UML序列圖是從https://github.com/bramp/js-sequence-diagrams copy得到的。

當如這個UML代碼還用到了兩個JS,功能庫和畫圖.

<script src="underscore-min.js"></script>
<script src="raphael-min.js"></script>

首先講講這個JS最核心的類:
https://github.com/bramp/js-sequence-diagrams/blob/master/src/sequence-diagram.js

首先這個類分爲其實使用兩種風格的。一種就是現在CSDN採用的風格,叫做simple. 另外一種是手繪風格,叫做hand。定義如下:

var themes = {
simple : RaphaelTheme,
hand : HandRaphaelTheme
};
Diagram.prototype.drawSVG = function (container, options) {
var default_options = {
theme: 'hand'
};
options = _.defaults(options || {}, default_options);
if (!(options.theme in themes))
throw new Error("Unsupported theme: " + options.theme);
var drawing = new themes[options.theme](this);
drawing.draw(container);
}; // end of drawSVG

drawSVG是最外層JS要畫圖調用的方法。例如:

<div id="diagram">Diagram will be placed here</div>
<script src="sequence-diagram-min.js"></script>
<script> 
  var diagram = Diagram.parse("A->B: Does something");
  diagram.drawSVG('diagram');
</script>

下面就可以畫出圖形。所以drawSVG是核心入口。

drawSVG的實現過程中,最重要的一句:

drawing.draw(container);

這一句調用的draw function定義如下:

    draw : function(container) {
        var diagram = this.diagram;
        this.init_paper(container);
        this.init_font();
        this.layout();
        var title_height = this._title ? this._title.height : 0;
        this._paper.setStart();
        this._paper.setSize(diagram.width, diagram.height);
        var y = DIAGRAM_MARGIN + title_height;
        this.draw_title();
        this.draw_actors(y);
        this.draw_signals(y + this._actors_height);
        this._paper.setFinish();
},

這幾句看起來平淡無奇,就是初始化背景,初始化字體,初始化各種,然後畫標題,畫角色(也就是序列圖中的實體),畫調用箭頭。

這裏面看似簡單,但是最爲繁瑣的就是:

this.layout();

佈局:要遍歷所有的要畫到畫布上的東西,要提前預知,各個東西的長寬,然後根據長寬,各個東西相距的距離,算出畫布的尺寸。這段JS並沒有做到固定長寬後,各個東西等比縮放。

這個做完之後,開始畫角色(也就是實體)

Created with Raphaël 2.1.2AA這就是角色A包括上下兩個方塊和中間的豎線

再然後,兩個角色之間是有間距的。例如:

Created with Raphaël 2.1.2距離是什麼?AABB我們兩個角色之間的間距包括上下兩個方塊和中間的豎線

間距的計算並不是很容易,首先確定每個角色的基本的高和寬,然後根據將信號signal計算在內(signal 包括兩種,一種是 箭頭關係,另外一種是 註釋框)所以大家可以看到註釋框和箭頭也是有從上到下的順序的。signal的寬度和字的個數以及寬度均有關係(這裏計算較爲複雜,此處略去太多字…有興趣的看源碼)。

然後順序遍歷,依次確定A,B,C…各個角色所在的絕對座標。

每一個signal都是有高度的,將所有的signal 高度加和,就得到了下端角色方框的座標。然後連線就大功告成。

看源碼發現了許多沒有的功能…

例如 UML中增加title
以及UML中註釋框除了Right, Left, 還有Over, 對於Over還可以置於多個角色之上。

title 和 Over

```sequence
title: 距離是什麼?

A->B: 我們兩個角色之間的間距
Note Over A,B: 包括上下兩個方塊和中間的豎線
Note Over A: I'm A
```

表現:

Created with Raphaël 2.1.2距離是什麼?AABB我們兩個角色之間的間距包括上下兩個方塊和中間的豎線I'm A

https://github.com/bramp/js-sequence-diagrams/blob/master/src/jquery-plugin.js

這裏寫圖片描述

這個類中,如果沒有定義option屬性,那麼就只能用simple的形式了。感覺CSDN的dev好像沒有定義這個option. 我這邊也無能爲力。

[https://github.com/bramp/js-sequence-diagrams/blob/master/src/diagram.js] 這個類沒有什麼好講的,就是通過parser構造出來的實體類。

剩下的兩個gammar JS. 這種詞法解析的放到後面一篇再說. 網絡實在不好,啥都timeout, 另外也該睡覺了。

發佈了570 篇原創文章 · 獲贊 39 · 訪問量 138萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章