orgchart
v6.0.0
Published
Simple and direct organization chart(tree-like hierarchy) library based on pure DOM.
Maintainers
Readme
Read this in other languages: 简体中文, English
ES6版
Web Components版
Vue.js版
Angular版 -- 最節省空間的解決方案
React版
寫在前面的話
感謝wesnolte的非常棒的作品-- jOrgChart。用嵌套的table來構造樹狀結構,用td的border來構造節點間的連線,非常有創意。天然地降低了前端程序員在構造樹狀結構時的工作量和難度,要知道,利用D3.js中的腦圖去達到同樣效果,開發周期就會長好多。哪怕你對svg,canvas等高級的制圖API了然于胸,當你的樹狀結構圖激發出HR大姐的各種天馬行空的需求時,你會坦誠的承認svg或canvas這種重型武器拖累了你的快速解決一小戳敵人的能力。相比較而言,用單純的HTML5 + CSS3的解決方案就像是 “小米 + 步槍”的輕步兵,天然地降低了你在實現樹狀結構圖的難度,同時給予你更大的定制空間去面對基于這個結構圖衍生出的種種瑣碎需求。只要你的需求足夠多,基于這個樹狀結構圖,打造出一個完備的HR系統,也是可以期待的。實際上,網絡上很多OrgChart商業軟件就是圍繞著一個樹狀結構核心模型展開的業務邏輯實現。
- 自 5.0 版本起,使用者可以建立家譜樹。
- 自 6.0 版本起,OrgChart 元件已回歸原生實作,不再依賴 jQuery。
功能特性
- 支持本地和遠程的數據源。
- 用戶可以展開/折疊節點或子樹,方便地浏覽局部的結構圖。
- 上下左右4個方向的布局。
- 用戶可以通過拖放節點或子樹的方式來改變組織結構圖的形態。
- 用戶可以編輯組織結構圖的層次結構並將最終結果保存爲JSON對象。
- 支持將組織結構圖導出爲png圖片或pdf文檔。
- 支持對組織結構圖的縮放/平移
- 用戶可以自行定制節點的內部結構,例如插入員工照到節點中。
- 用戶可以采用不同的數據源構建多層級的組織結構圖(請參考多層組織結構圖和混合布局組織結構圖的實例)。
- 支持移動設備上的多點觸控操作。
CDN
可以在CDN上找到本插件的對應資源。
https://cdnjs.com/libraries/orgchart
安裝
Bower
# From version 1.0.2 on, users can install orgchart and add it to bower.json dependencies
$ bower install orgchartnpm
# From version 1.0.4 on, users can install orgchart with npm
$ npm install orgchart在 CommonJS 環境中,require('orgchart')會直接導出 OrgChart 構造函數。
可參考這個例子, 在React中使用jQuery Orchart
gihtub pages實例集合
基于嵌套ul的實例集合
基于嵌套table的實例集合 (過時)
天馬行空的需求
我想以不同的方向布局組織結構圖(感謝 fvlima 和 badulesia 的好點子 :blush:)
從上到下 -- 默認的布局方向

這裏使用了第三方的工具html2canvas.
注意:
(1) 如果你想在IE或Edge導出,請先引入es6-promise.auto.js到項目中.
(2) 如果你的操作系統是Windows,請先檢查“縮放設置”,需調整"Change the size of text, apps, and other items" to 100%.(感謝sayamkrai的研究)
(3) 此外,如果你想導出成pdf文件, 請先引入jspdf到項目中,然後設置"exportFileextension"選項爲"pdf"。
這裏,我們需要求助于OpenLayers。
本插件中暴露來若幹方法--addParent(), addSiblings(), addChildren(), removeNodes(),可以幫助開發者很方便的實現上述需求。
一旦啓用了"draggable"選項,我們就可以通過拖放來改變組織結構圖的層次結構了。但是注意,這個特性在IE浏覽器上不工作。後續地,我們還可以利用dropCriteria選項,來定制更細致的拖放限制准則。默認情況下,插件只提供了一條限制准則--不能直接把父節點放到它的子節點裏。
我們有個getHierarchy()方法,專門幹這事。
我們只需要把css的樣式與數據源中的id字段或css類字段關聯起來就好。
這個特性的靈感來源于這兩個話題的討論--Aligning Children Vertical, Hybrid(horizontal + vertical) OrgChart。感謝mfahadi和Destructrix建設性的討論:blush:尤其感謝tedliang提供了非常棒的混合布局的解決方案。
這個好辦。在數據源中,給父節點追加'collapsed': true,給子節點追加'className': 'slide-up'。
我們暴露了init()方法幫你完成上述任務,把新的option傳到init()方法裏就好了。
沒問題,我們推薦使用ES6的模版字符串。

你需要的是一個復合的解決方案: levelOffset data prop + callback createNode() + CSS custom properties(variables)


hybrid data property 就派上用場了。 在數據源的某個節點中提供"hybrid"屬性,那麽它的所有後代節點都會垂直布局。

compact data property 就派上用場了。在數據源的某個節點裏提供了"compact"屬性,並賦為真值,那麽它和它的子節點就會展示為壓縮模式。

我們使用如下的二維數組數據源來構建家譜。“outsider”代表外姓人。
var datascource = [
[
{ 'id': '8', 'name': 'Lao Ye', 'title': 'Grandfather' },
{
'id': '1', 'name': 'Lao Lao', 'title': 'Grandmother', 'outsider': true,
'children': [
[
{ 'id': '2', 'name': 'Bo miao', 'title': 'Aunt' }
],
[
{ 'id': '3', 'name': 'Su Miao', 'title': 'Mother',
'children': [
[
{ 'id': '12', 'name': 'Pang Pang', 'title': 'Wife', 'outsider': true,
'children': [
[{ 'id': '7', 'name': 'Dan Dan', 'title': 'Daughter' }],
[{ 'id': '6', 'name': 'Er Dan', 'title': 'Daughter' }],
]
},
{ 'id': '5', 'name': 'Hei Hei', 'title': 'Me' },
]
]
},
{ 'id': '9', 'name': 'Tie Hua', 'title': 'Father', 'outsider': true }
],
[
{ 'id': '10', 'name': 'Hong miao', 'title': 'Aunt' }
]
]
}
]
];

啓用 minimap 選項即可顯示概覽導航器。拖動其中的視口可以移動組織結構圖,在小地圖上滾動鼠標滾輪可以縮放。
本地運行orgchart
- 必須安裝node.js v6+,因爲我們的單元測試是基于jsdom v11。
- 必須安裝現代浏覽器(忽略IE浏覽器)。因爲orgchart插件幾乎所有的行爲和特性都是基于HTML5和CSS3環境下開發與測試的。
- 運行命令
npm install來安裝必要的依賴。 - 運行命令
npm test來跑所有的測試(單元測試,集成測試,端到端測試,以及視覺回歸測試) - 運行命令
npm run build來生成生産版本的js,css文件。 - 運行命令
npm start來啓動本地web server,在這個地址http://localhost:3000 上查看滿足不同場景需求的Demo。
使用
實例化組織結構圖
var oc = new OrgChart({
chartContainer: '#chartContainerId',
data: datasource
});數據源示例
{
'id': 'rootNode', // 可選屬性。將來插件會基于它,創建節點的id,data-parent(當前節點的父節點的id屬性)等特性
'collapsed': true, // 默認初始化時,當前節點處于折疊狀態,其子節點不顯示
'className': 'top-level', // 可選屬性。將來組件會把它的值追加到節點的CSS 類中
'nodeTitle': 'name', // 可選屬性。插件會以該屬性的值爲屬性,
// 來檢索數據源,然後渲染默認結構樣式的節點的上半部分
'nodeContent': 'title', // 可選屬性。插件會以該屬性的值爲屬性,
// 來檢索數據源,然後渲染默認結構樣式的節點的下半部分
'relationship': relationshipValue, // 注意:當你激活按需載入節點特性時
// 你應該使用JSON數據源(不論本地或遠程)並設置本屬性
// 本屬性標識當前節點是否具有父節點,兄弟節點,子節點
// relationshipValue的值是由“0”或“1”組成的長度爲3的字符串
// 第1個字符代表當前節點是否具有父節點
// 第2個字符代表當前節點是否具有兄弟節點
// 第三個字符代表當前節點是否具有孩子節點
'children': [ // The property stands for nested nodes.
{ 'name': 'Bo Miao', 'title': 'department manager', 'relationship': '110' },
{ 'name': 'Su Miao', 'title': 'department manager', 'relationship': '111',
'children': [
{ 'name': 'Tie Hua', 'title': 'senior engineer', 'relationship': '110' },
{ 'name': 'Hei Hei', 'title': 'senior engineer', 'relationship': '110' }
]
},
{ 'name': 'Yu Jie', 'title': 'department manager', 'relationship': '110' }
],
'otherPro': anyValue // 數據源中可以追加任意其他字段,只要你覺得
// 在之後的渲染和操作組織結構圖時派得上用場
};選項
方法
使用 new OrgChart(options) 建立實例。chartContainer 和 chart 屬性分別提供原生容器元素與已渲染的組織結構圖元素。
const oc = new OrgChart({ chartContainer: '#chartContainerId', data: datasource });公開 API 包括:init、setOptions、attachMinimap、detachMinimap、updateMinimap、addAncestors、addDescendants、addParent、addSiblings、addChildren、removeNodes、getHierarchy、getNodeState、getParent、getChildren、getSiblings、getRelatedNodes、hideParent、showParent、hideChildren、showChildren、hideSiblings、showSiblings、setChartScale、export、exportPNG 和 exportPDF。其中節點和圖表參數均為原生 HTMLElement。
API 參考
| 呼叫 | 參數 | 回傳值與呼叫行為 |
| --- | --- | --- |
| oc.init(options) | 部分選項物件;傳入 data 可替換資料來源。 | 重新建立圖表並回傳 oc。 |
| oc.setOptions(options)oc.setOptions(name, value) | 包含 data、pan、zoom 或 minimap 的物件;或受支援的選項名稱及布林值。 | data 會重建圖表,其他選項切換相應功能;回傳 oc。 |
| oc.attachMinimap()oc.detachMinimap()oc.updateMinimap(forceRefresh) | forceRefresh 可選;傳入 true 會重繪節點預覽。 | 建立、移除或刷新小地圖。一般啟用應使用 setOptions('minimap', value)。 |
| oc.addAncestors(data, parentId) | 祖先資料,以及接收原根節點的祖先節點 id。 | 插入祖先層級;無回傳值。 |
| oc.addDescendants(data, parent) | 後代資料陣列和已渲染的父 .node。 | 附加後代層級;無回傳值。 |
| oc.addParent(currentRoot, data) | 已渲染的根 .node 和新父節點資料。 | 用新父節點包裹目前根;無回傳值。 |
| oc.addSiblings(node, data)oc.addChildren(node, data) | 已渲染的 .node 和兄弟節點或子節點資料陣列。 | 增加渲染節點;無回傳值。 |
| oc.removeNodes(node) | 要刪除的已渲染 .node。 | 刪除該節點及其後代;無回傳值。 |
| oc.getHierarchy(includeNodeData) | 可選布林值,預設 false。 | 回傳層級物件;圖表或必要節點 id 不可用時回傳錯誤字串。 |
| oc.getNodeState(node, relation) | 已渲染 .node;relation 為 parent、children 或 siblings。 | 回傳 { exist, visible }。 |
| oc.getParent(node) | 已渲染 .node。 | 回傳父 .node,不存在時回傳 null。 |
| oc.getChildren(node)oc.getSiblings(node) | 已渲染 .node。 | 回傳直接子節點或兄弟節點 .node 元素陣列。 |
| oc.getRelatedNodes(node, relation) | 已渲染 .node;relation 為 parent、children 或 siblings。 | 通用關聯查詢;parent 回傳節點或 null,其他關係回傳陣列。 |
| oc.hideParent(node) / oc.showParent(node)oc.hideChildren(node) / oc.showChildren(node) | 已渲染 .node。 | 透過圖表過渡隱藏或顯示關聯分支;無回傳值。 |
| oc.hideSiblings(node, direction)oc.showSiblings(node, direction) | 已渲染 .node;可選 direction 為 left 或 right。 | 隱藏或顯示指定一側的兄弟節點;省略方向時處理全部兄弟節點;無回傳值。 |
| oc.setChartScale(chart, multiplier, zoomAnchor) | 通常傳入 oc.chart;正數的相對縮放倍數;可選視口座標 { x, y }。 | 在配置的縮放範圍內縮放,提供 zoomAnchor 時固定該點。 |
| oc.export(filename, extension) | 可選檔案名稱和 png 或 pdf 副檔名。 | 按配置預設值開始匯出;無法匯出時回傳 false。 |
| oc.exportPNG(canvas, filename)oc.exportPDF(canvas, filename, exportScale) | 已準備的 canvas、檔案名稱;PDF 縮放預設 1。 | 將傳入 canvas 直接下載為 PNG 或 PDF;通常應呼叫 export()。 |
init(newOptions)
當你想基于新的options或數據源刷新組織結構圖時,這個方法就派上用場了。
setOptions(options) / setOptions(name, value)
無需重新建立圖表即可更新 pan、zoom 或 minimap。可傳入選項物件,或傳入支援的選項名稱和布林值;傳入包含 data 的物件時會重新建立圖表。
attachMinimap() / detachMinimap()
建立或移除目前圖表的小地圖覆蓋層。通常應使用 setOptions('minimap', true|false),以確保選項狀態和覆蓋層保持同步。
updateMinimap(forceRefresh)
在修改圖表變換或版面配置後重新計算小地圖視口。傳入 true 會重繪小地圖中的節點預覽。
addAncestors(data, parentId)
爲當前的組織結構圖增加祖先節點,可以不止壹個層級。
addDescendants(data, parent)
爲指定的父節點增加後代節點。
addParent(currentRoot, data)
爲當前的組織結構圖增加父節點。
addSiblings(node, data)
爲指定的節點增加兄弟節點。
addChildren(node, data)
爲指定的節點增加孩子節點。
removeNodes(node)
刪除指定的節點及其後代節點。
getHierarchy()
這個方法被設計用來提供組織結構圖的層次結構關系。舉個例子,當你采取某種手段對當前的組織結構圖的結構進行了改動後,可以調用本方法獲得最新的結構,並將其保存到後台。
hideParent(node)
隱藏指定節點的父節點。當然其兄弟節點及祖先節點也一並隱藏了。
showParent(node)
顯示指定節點的父節點。但不包括更上一層的祖先節點。
hideChildren(node)
隱藏指定節點的孩子節點。當然這其中包含了所有的後代節點。
showChildren(node)
顯示指定節點的孩子節點。默認只顯示緊鄰的下一個層級,並不包括所有的後代節點。
hideSiblings(node, direction)
隱藏指定節點的兄弟節點。
showSiblings(node, direction)
顯示指定節點的兄弟節點。
getNodeState(node, relation)
該方法幫你了解指定節點的相關節點的顯示狀況。
本方法的返回對象的結構如下:
{
"exist": true|false, // 標識你想了解的父節點,孩子節點,兄弟節點是否存在
"visible":true|false, // 標識相關節點當前是否可見
}getRelatedNodes(node, relation)
獲得指定節點的關聯節點。
getParent(node)
回傳指定節點的父節點;如果不存在父節點,則回傳 null。
getChildren(node)
回傳指定節點的直接子節點陣列。回傳值中的每一項都是原生 HTMLElement。
getSiblings(node)
回傳指定節點的兄弟節點陣列。回傳值中的每一項都是原生 HTMLElement。
setChartScale(chart, newScale, zoomAnchor)
用這個方法可以幫你爲指定的組織結構圖設置新的scale系數。
zoomAnchor 為可選參數,格式為視口座標 { x, y }。提供該參數後,縮放時會固定該座標點。
export(exportFilename, exportFileextension)
將當前的組織結構圖導出爲png圖片或pdf文檔。
exportPNG(canvas, exportFilename)
將準備好的 canvas 匯出為 PNG 下載。當應用程式自行提供 canvas 時可直接呼叫;大多數情境應使用 export()。
exportPDF(canvas, exportFilename, exportScale)
將準備好的 canvas 匯出為 PDF 下載。exportScale 是 canvas 的渲染縮放比例,用於保持 PDF 的邏輯尺寸;大多數情境應使用 export()。
事件
OrgChart 會派發可冒泡的原生 CustomEvent。請使用 addEventListener 訂閱,事件參數位於 event.detail。
oc.chart.addEventListener('nodedrop.orgchart', function (event) {
const { draggedNode, dragZone, dropZone } = event.detail;
});Tips
默認的展開/折疊節點功能雖然很好,但是我想禁掉它,咋辦?
關于這個需求的展開討論可以看這個問題。感謝der-robert和ActiveScottShaw的非常有建設性的討論:blush:
我們提供了一個CSS類"noncollapsable",可以方便地完成這件事。
oc.chart.classList.add('noncollapsable'); // 禁掉展開/折疊
oc.chart.classList.remove('noncollapsable'); // 開啓展開/折疊爲啥根節點消失了,看不到了?
比如說我渲染了一個非常龐大的組織結構圖,同時我啓用了“平移”特性,這時如果我隱藏掉某個節點的大量的後代節點,可能會導致上層的一些節點在當前可視區域內消失。 跟多的細節,可以參考這個問題的討論。感謝manuel-84 的問題抛出 :blush:
浏覽器兼容性檢查
- Chrome 19+
- Firefox 4+
- Safari 6+
- Opera 15+
- IE 10+
