做者:心葉
時間:2018-11-06 14:47node
舒適提示:clay.js已經中止維護,項目遷移到 https://github.com/yelloxing/...
喜歡本項目的能夠在github上給給star。git
在繪製一些常見圖形的時候,好比關係圖,單個結點或連線並不難,麻煩的是位置的計算等,和圖形模塊不一樣,佈局就是專門計算一些特殊圖形位置的模塊,用一句通俗的話說就是:決定什麼元素繪製在哪裏。所以,佈局應該和具體的繪圖方法無關,她只關心位置的計算。github
下面,咱們將經過介紹一個最簡單的樹圖的繪製過程來講明佈局的設計理念,讓咱們開始吧!數組
$$('<svg>' + // 繪製連線 '<g class="line"></g>' + // 繪製結點 '<g class="node"></g>' + // 繪製文字 '<g class="text"></g>' + '</svg>').appendTo('body') .attr('width', '400') .attr('height', '400');
上圖是最終運行結果,上面咱們準備好了畫布,須要繪圖的原始數據以下:數據結構
var nodes = [ // 結點名稱、父節點名稱 ["手繪", null], ["水粉", "手繪"], ["油畫", "手繪"], ["素描", "手繪"], ["中國畫", "手繪"], ["空間透視", "素描"], ["色彩五大調", "素描"], ];
使用佈局繪圖的第一步是建立佈局對象,這裏是建立tree佈局對象:app
// 建立佈局對象 var tree = clay.treeLayout();
理論上來講,原始數據能夠是任意格式,只要保證總體是一個數組便可。這主要是考慮到實際開發複雜的環境,所以,提供了數據格式配置接口,對於上面的數據,進行以下配置:svg
tree // 獲取根結點 .root(function (initTree) { return initTree[0]; }) // 獲取孩子結點 .child(function (parentTree, initTree) { var children = [], i; for (i = 0; i < nodes.length; i++) { if (initTree[i][2] == parentTree[0]) children.push(initTree[i]); } return children; }) // 獲取結點標誌id .id(function (treedata) { return treedata[0]; })
不一樣佈局須要配置的項不同,對於tree佈局而言,關於數據結構的部分,只須要告訴她如何根據父結點獲取子結點,一個結點的惟一標識怎麼肯定,根節點是誰。佈局
開頭就說明的很清楚了,佈局應該是和具體繪圖方式無關的存在,所以,這裏咱們選擇了svg繪圖,就須要再配置一下具體的繪圖方法。this
tree.drawer(function (nodes, rootid, size) { var i, node; for (i in nodes) { node = nodes[i]; // 繪製結點 $$('<circle target=' + node.data[0] + ' r="3" fill="white" stroke="red" stroke-width="1"/>') .appendTo('.node') .attr('cx', node.left * 100) .attr('cy', node.top * 100); // 繪製文字 $$('<text style="font-size:10px;">' + node.data[0] + '</text>') .appendTo('.text') .attr('x', node.left * 100) .attr('y', (node.top * 100 - 14)); // 繪製連線 if (node.pid) $$('<path source=' + node.data[1] + ' target=' + node.data[0] + ' stroke-width="1" stroke="gray" fill="none"></path>') .appendTo('.line') .attr('d', 'M' + nodes[node.pid].left * 100 + " " + nodes[node.pid].top * 100 + "C" + (nodes[node.pid].left * 100 + 50) + "," + nodes[node.pid].top * 100 + " " + (node.left * 100 - 50) + "," + node.top * 100 + " " + node.left * 100 + "," + node.top * 100 + " "); } });
到這裏,全部必須的配置都寫好了,添加下面這行代碼,啓動繪圖:spa
tree(nodes);
至此,運行代碼就能夠看見一棵記錄着結點關係的樹圖了,繪圖結束!
由於佈局不會知道最終繪製的圖形具體是什麼樣子,好比這裏的樹佈局,也許你想繪製的是旋轉的樹或倒樹,也可能你就是想要和這裏同樣的簡單樹。爲了防止問題複雜化,佈局在計算位置的時候,都會統一選擇一種最樸素的場景做爲計算模型,從該模型出發,任何別的模型藉助clay提供的一些計算方法實現起來就很容易了。
上圖是tree佈局的計算模型。右邊的每一個紅色矩形都是一個1x1的正方形,座標原心位於左上角綠色頂點。
配置具體繪圖方式的時候,其中第一個參數nodes就記錄了每一個結點通過佈局計算後的位置信息,讓咱們打印一下其中的一條數據看看:
"油畫":{ children: []; data: (2) ["油畫", "手繪"]; id: "油畫"; left: 1.5; pid: "手繪"; show: true; top: 1.5 }
其中data記錄着結點的原始數據,咱們主要看看left和top,這顯示該結點應該繪製的座標爲(1.5,1.5),對照上圖,是否是就很清晰了。別的佈局的設計思想也是如此,請耐心體會一下!
// 添加交互用例 $$('circle').bind('click', function () { // 刪除結點 tree.delete($$(this).attr('target')); });
其實交互和佈局應該是沒有關係的,始終強調,佈局只負責計算繪圖的位置,好比上面的結點刪除例子,綁定點擊事件,調用結點的刪除結點方法便可。刪除方法刪除的只是佈局保存的數據,而後重繪畫面,若是你須要畫面平滑改變,修改繪圖實現方法便可,這裏再也不贅述。