
事件太多,拉起時間軸傷透腦筋嗎?時間軸是常見的視覺化手法,但現成工具往往缺乏變化,手繪又曠日費時。不要緊!Labella.js 幫我們自動排版標籤,從此麻煩事就交給他,完成事情更有效率!
繪製時間軸難免得為事件標上細節,但我們常會碰到幾個問題:
- 內容往往視資料而定,可長可短可大可小
- 資料點有時很稀疏,有時又很密集
- 手動對應時間點的位置很麻煩,但大多數時間軸工具例如 timeline.js 又缺乏客製的彈性
在自行排版時間軸標籤時,牽涉到的大多是操作式的無聊動作,這樣的任務便是程式自動化的最好對象。 Labella.js 是一個時間軸的標籤套件,他可以為我們標記事件在時間軸上的位置,並自動排版標籤至適當位置,除了省時省力外,排版出來的結果還不錯看!比方說,下圖為截自 Labella.js 的示範頁面:

在這個範例中我們彈性的設定各種屬性,標籤便會自動依照我們的選擇擺放位置。它的輸出甚至是 SVG ,我們很輕易的就可以利用 SVG Crowbar 等工具 ( 請參考先前的:SVG Crowbar — 視覺化一鍵打包帶回家 ) 介紹把他整組下載來修改。完美!
但是,很可惜的這個範例中並沒有讓我們填事件細節的地方,也因此產生的時間軸只能做為參考,若要直接拿來用,還是得重新調整半天。沒關係, Labella.js 正如其名,是個 JavaScript 函式庫,我們可以運用他所提供的 API 來打造自己的時間軸。
( 編按:如果你不會寫程式,我們直接在文章最後提供了一個做好的時間軸標籤產生器,可以直接拉到底玩玩看喔!)
首先,將 Labella.js 引入網頁中,並準備一個 SVG 標籤 ( id 亦設為 “svg" ):
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/labella/1.1.2/labella.min.js"></script> <svg id="svg" width="800px" height="500px" viewBox="0 0 800 500"></svg>
接著以下列程式碼產生標籤排版資料:
// 一共三組資料,對應位置在 10, 20, 30,標籤寬度 100, 80, 60 var nodes = [ new labella.Node(10,100), new labella.Node(20,80), new.labella.Node(30,60), ]; nodes = new labella.Force().nodes(nodes).compute().nodes();
接著我們利用 Labella 的 Renderer 函式搭配 D3.js 繪製標籤:
// 計算位置 var renderer = new labella.Renderer(); nodes = renderer.layout(nodes); // 建立分組標籤 d3.select("#svg").selectAll("path").data(nodes).enter() .append("g").each(function(d,i) { var node = d3.select(this); // 繪製連線 node.append("path").attr({ d: renderer.generatePath, fill: "none", stroke: "crimson" }); // 繪製標籤 node.append("rect").rect({ x: function(it) { return it.x - it.dx / 2 ; }, y: function(it) { return it.y; }, width: function(it) { return it.dx; }, height: function(it) { return it.dy; }, fill: "crimson" }); });
產生的結果如下:

利用 d3Kit-timeline
雖然我們成功做出了一個時間軸雛型,但還有很多沒搞定的,包含軸線、軸點、標籤文字等等問題,再這樣搞下去輕鬆都不輕鬆了。沒關係, Labella.js 作者深知民間疾苦,他將 Labella.js 搭配包裝成另一個好用的工具 — d3Kit-timeline !
d3Kit-timeline 透過包裝繪圖的細節讓我們省掉大部份上述的工,而透過 D3.js 則為我們保留了許多彈性。這裡我們直接引用 d3Kit-timeline usage 裡的程式碼簡單為大家做解說。
首先,引入必要的函式庫;除了 d3.js 與 labella.js 以外,我們需要另外取得 d3kit 與 d3kit-timeline:
<script src="d3.min.js"></script> <script src="d3kit.min.js"></script> <script src="labella.min.js"></script> <script src="d3kit-timeline.min.js"></script>
接著設定我們要用的資料,這裡使用的資料是星際大戰電影各集的年代與名稱:
var data = [ {time: new Date(1977, 4,25), name: 'A New Hope'}, {time: new Date(1980, 4,17), name: 'The Empire Strikes Back'}, {time: new Date(1984, 4,25), name: 'Return of the Jedi'}, {time: new Date(1999, 4,19), name: 'The Phantom Menace'}, {time: new Date(2002, 4,16), name: 'Attack of the Clones'}, {time: new Date(2005, 4,19), name: 'Revenge of the Sith'}, {time: new Date(2015,11,18), name: 'The Force Awakens'} ];
然後使用 d3Kit-timeline 繪制時間軸:
chart = new d3KitTimeline('#svg', { direction: 'down', // 朝下的時間軸標籤 initialWidth: 800, labella: {maxPos: 800}, // 控制圖表寬度 textFn: function(d) { return d.time.getFullYear() + ' - ' + d.name } });
chart.data(data).resizeToFit();
產生結果如下:

Labella UI
即便 Labella + d3Kit-timeline 相當的方便,對於不會寫程式的讀者來說仍然是無法使用,沒關係!小編將上列的範例程式碼整理成一個可以動態填入資料的線上版本,如果你想要嘗試看看,直接玩玩看吧:
這裡提供另一段範例資料供讀者參考,可以試著在上方的文字框中貼上:
time,name 1983/4/18,US Embassy bombing 1983/12/12,Kuwait bombings 1989/7/7,Jerusalem Bus Suicide Attack 1993/2/26,WTC Bombing 1993/3/12,Serial Blasts in Mumbai 1994/12/24,Flight Hijacking in Algiers 1996/6/5,Khobar Towers Bombing 1997/11/17,Luxor Massacre 1998/2/14,Coimbatore Bomb Attacks 1998/8/7,US Embassy bombing 2000/10/12,Yemeni Attack 2000/12/22,Delhi Attack 2000/12/24,Indonesia Bombings 2001/9/11,911
這組範例資料的產生結果類似下圖:

我們也在其中提供了基本設定顏色的功能,但最後你都可以利用 SVG Crowbar 下載後再利用 Adobe Illustrator 或是 Vectr.com 做調整。若你未來想再使用這個小工具,你可以儲存這篇文章供參考,或直接將這個小工具的網址 ( http://infographicstw.github.io/labella-ui/ ) 加入書籤。
結語
Labella.js 為來自 Twitter 的 Krist Wongsuphasawat 開發,在其程式碼中也可以看到類似 D3.js 結構的設計,而正如 D3.js 其中強大的一面 — 「不光是給你圖表,而是幫你計算各種版面」一般, Labella 也可以想成是一個 d3.layout 的實用擴充。或者說,原本作者就是以這樣的思維來設計的吧!