Read this in other languages: 繁體中文, English

August 20, 2026 · View on GitHub

OrgChart

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上找到本插件的对应资源。

cdnjs 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 orgchart

npm

# 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的实例集合 (过时)

天马行空的需求

10000-nodes

ondemand-loading-data

这里使用了第三方的工具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。感谢mfahadiDestructrix建设性的讨论:blush:尤其感谢tedliang提供了非常棒的混合布局的解决方案。

这个好办。在数据源中,给父节点追加'collapsed': true,给子节点追加'className': 'slide-up'

我们暴露了init()方法帮你完成上述任务,把新的option传到init()方法里就好了。

没问题,我们推荐使用ES6的模版字符串。

level-offset

你需要的是一个复合的解决方案: levelOffset data prop + callback createNode() + CSS custom properties(variables)

nodes-of-different-widths

data-prop-hybrid

hybrid data property 就派上用场了. 在数据源的某个节点中提供"hybrid"属性,那么它的所有后代节点都会垂直布局.

data-prop-compact

compact data property 就派上用场了. 在数据源的某个节点里提供了"compact"属性,并赋为真值,那么它和它的子节点就会展示为压缩模式。

family-tree

我们使用如下的二维数组数据源来构建家谱。“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' }
        ]
      ]
    }
  ]
];

familytree-custom-properties

minimap

启用 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 // 数据源中可以追加任意其他字段,只要你觉得
  // 在之后的渲染和操作组织结构图时派得上用场
};

选项

名称 类型 必填 默认值 描述
data json / HTMLUListElement 用于构造组织结构图的数据源。它的值可以是JSON或能提供数据的ul元素。
pan boolean false 启用本选项,用户可以通过鼠标拖拽组织结构图。
zoom boolean false 启动本选项,用户可以通过鼠标滚轮或触摸板对组织结构图进行缩放。
zoominLimit number 7 放大的上限值
zoomoutLimit number 0.5 缩小的下限值
direction string "t2b" 该选项用来设置布局方向。"t2b"代表从上到下,是默认值。"b2t"代表从下到上。"l2r"代表从左到右。"r2l"代表从右到左。
verticalLevel integer(>=2) 表示组织结构图从哪一层开始,从水平布局节点转变为垂直布局节点。
toggleSiblingsResp boolean false 启动该选项,用户点击了节点的两侧箭头按钮时,会展开/折叠一侧的兄弟节点;默认的行为是用户点击了节点任何一侧的箭头按钮,都会折叠起所有的兄弟节点,不区分左右。
visibleLevel positive integer 999 该选项为用户指定初始化组织结构图时,可见的展开的层级是多少
nodeTitle string "name" 将默认节点结构中的标题部分关联到数据源中的一个属性
parentNodeSymbol string "oci-leader" 为所有父节点的icon标识指定CSS类名
nodeContent string 将默认节点结构中的内容部分关联到数据源中的一个属性
nodeId string no "id" 选取一个数据源中的字段作为组织结构图中的每个节点的唯一标识
nodeTemplate function 应该为该选项提供一个节点结构模版生成函数,该函数只接收一个参数,就是涵盖子树渲染的数据源片段。
createNode function 为该选项提供的函数,会在默认节点结构创建完毕后调用。利用传入的两个参数--"node"和"data",可以帮助开发者定制或改动现有的节点结构。
exportButton boolean false 启用该选项,插件会追加“导出”按钮到组织结构图的容器DIV里。
exportButtonName string "Export" 导出按钮的名字。
exportFilename string "Orgchart" 导出文件的文件名。
exportFileextension string "png" 导出文件的扩展名。
chartClass string "" 通过指定该选项,来给组织结构图追加自定义的CSSl类名,尤其是在你的组织结构图容器中要承载夺冠chart的时候,这个选项就显得很重要了。
draggable boolean false 启用该选项,用户就可以拖放节点的方式改变组织结构图的结构了。**注意:**将当前的某个父节点拖放到其下面的某个子节点里,这样的操作是不允许的。因为如果插件顺从了这样的操作,会产生孤立的子树;本选项在IE浏览器上不可用。
dropCriteria function 用户可以通过该选项定制更细致的拖放节点的限制准则。你需要为该选项提供一个返回boolean值的函数,该函数用来判断当拖放操作结束时,是否允许将当前拖拽的节点从拖动区域摘出来插入到松放区域里。该函数接受3个参数--draggedNode, dragZone, dropZone。
initCompleted function 组织结构图初始化完成后,该选项指定的回调函数被触发。该函数接受一个参数--"chart", 即初始化后的组织结构图元素。

方法

使用 new OrgChart(options) 创建实例。chartContainerchart 属性分别提供原生容器元素与已渲染的组织结构图元素。

const oc = new OrgChart({ chartContainer: '#chartContainerId', data: datasource });

公开 API 包括:initsetOptionsattachMinimapdetachMinimapupdateMinimapaddAncestorsaddDescendantsaddParentaddSiblingsaddChildrenremoveNodesgetHierarchygetNodeStategetParentgetChildrengetSiblingsgetRelatedNodeshideParentshowParenthideChildrenshowChildrenhideSiblingsshowSiblingssetChartScaleexportexportPNGexportPDF。其中节点和图表参数均为原生 HTMLElement

API 参考

调用参数返回值与调用行为
oc.init(options)部分选项对象;传入 data 可替换数据源。重新构建图表并返回 oc
oc.setOptions(options)
oc.setOptions(name, value)
包含 datapanzoomminimap 的对象;或受支持的选项名称及布尔值。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)已渲染 .noderelationparentchildrensiblings返回 { exist, visible }
oc.getParent(node)已渲染 .node返回父 .node,不存在时返回 null
oc.getChildren(node)
oc.getSiblings(node)
已渲染 .node返回直接子节点或兄弟节点 .node 元素数组。
oc.getRelatedNodes(node, relation)已渲染 .noderelationparentchildrensiblings通用关联查询;parent 返回节点或 null,其他关系返回数组。
oc.hideParent(node) / oc.showParent(node)
oc.hideChildren(node) / oc.showChildren(node)
已渲染 .node通过图表过渡隐藏或显示关联分支;无返回值。
oc.hideSiblings(node, direction)
oc.showSiblings(node, direction)
已渲染 .node;可选 directionleftright隐藏或显示指定一侧的兄弟节点;省略方向时处理全部兄弟节点;无返回值。
oc.setChartScale(chart, multiplier, zoomAnchor)通常传入 oc.chart;正数的相对缩放倍数;可选视口坐标 { x, y }在配置的缩放范围内缩放,提供 zoomAnchor 时固定该点。
oc.export(filename, extension)可选文件名和 pngpdf 扩展名。按配置默认值开始导出;无法导出时返回 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)

无需重新构建图表即可更新 panzoomminimap。可传入选项对象,或传入支持的选项名称和布尔值;传入包含 data 的对象时会重新构建图表。

attachMinimap() / detachMinimap()

创建或移除当前图表的小地图覆盖层。通常应使用 setOptions('minimap', true|false),以保证选项状态和覆盖层保持同步。

updateMinimap(forceRefresh)

在修改图表变换或布局后重新计算小地图视口。传入 true 会重绘小地图中的节点预览。

addAncestors(data, parentId)

为当前的组织结构图增加祖先节点,可以不止一个层级。

名称 类型 必填 默认值 描述
data json 用于构造祖先节点的数据源
parentId string yes 将当前的组织结构图追加到某一个祖先节点里,该节点的id

addDescendants(data, parent)

为指定的父节点增加后代节点。

名称 类型 必填 默认值 描述
data array yes 用于构造后代节点的数据源
parent HTMLElement yes 后代节点要追加到的父节点对象

addParent(currentRoot, data)

为当前的组织结构图增加父节点。

名称 类型 必填 默认值 描述
currentRoot HTMLElement 当前组织结构图的根节点,新父节点会包裹这个根节点
data json object 构造根节点的数据源

addSiblings(node, data)

为指定的节点增加兄弟节点。

名称 类型 必填 默认值 描述
node HTMLElement 基于该节点增加其兄弟节点
data array 用于构造兄弟节点的数据源

addChildren(node, data)

为指定的节点增加孩子节点。

名称 类型 必填 默认值 描述
node HTMLElement 基于该节点增加其孩子节点
data array 构造孩子节点的数据源

removeNodes(node)

删除指定的节点及其后代节点。

名称 类型 必填 默认值 描述
node HTMLElement 待删除的节点。

getHierarchy()

这个方法被设计用来提供组织结构图的层次结构关系。举个例子,当你采取某种手段对当前的组织结构图的结构进行了改动后,可以调用本方法获得最新的结构,并将其保存到后台。

名称 类型 必填 默认值 描述
includeNodeData Boolean false 如果传入的该参数为true,那么导出的层次结构对象中就加入nodeData数据。

hideParent(node)

隐藏指定节点的父节点。当然其兄弟节点及祖先节点也一并隐藏了。

名称 类型 必填 默认值 描述
node HTMLElement Yes None 指定节点元素。

showParent(node)

显示指定节点的父节点。但不包括更上一层的祖先节点。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。

hideChildren(node)

隐藏指定节点的孩子节点。当然这其中包含了所有的后代节点。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。

showChildren(node)

显示指定节点的孩子节点。默认只显示紧邻的下一个层级,并不包括所有的后代节点。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。

hideSiblings(node, direction)

隐藏指定节点的兄弟节点。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。
direction string 可供选择的值有"left"和"rigth". 如果指定某一侧,就只隐藏某一侧的兄弟节点。如果不提供该参数,就隐藏所有的兄弟节点

showSiblings(node, direction)

显示指定节点的兄弟节点。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。
direction string 可供选择的值有"left"和"rigth". 如果指定某一侧,就只显示某一侧的兄弟节点。如果不提供该参数,就显示所有的兄弟节点

getNodeState(node, relation)

该方法帮你了解指定节点的相关节点的显示状况。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。
relation String 可选的值有--"parent", "children" 和 "siblings"。 指定明确的关系,然后本方法返回给你相关节点的显示状态。

本方法的返回对象的结构如下:

{
  "exist": true|false, // 标识你想了解的父节点,孩子节点,兄弟节点是否存在
  "visible":true|false, // 标识相关节点当前是否可见
}

getRelatedNodes(node, relation)

获得指定节点的关联节点。

名称 类型 必填 默认值 描述
node HTMLElement 指定节点元素。
relation String 可选的值有--"parent", "children" 和 "siblings"。用来指定具体的关系。

getParent(node)

返回指定节点的父节点;如果不存在父节点,则返回 null

getChildren(node)

返回指定节点的直接子节点数组。返回值中的每一项都是原生 HTMLElement

getSiblings(node)

返回指定节点的兄弟节点数组。返回值中的每一项都是原生 HTMLElement

setChartScale(chart, newScale, zoomAnchor)

用这个方法可以帮你为指定的组织结构图设置新的scale系数。

zoomAnchor 为可选参数,格式为视口坐标 { x, y }。提供该参数后,缩放时会固定该坐标点。

名称 类型 必填 默认值 描述
chart HTMLElement None 组织结构图容器中的某一个图。
newScale Float None 用于缩放组织结构图的缩放系数。

export(exportFilename, exportFileextension)

将当前的组织结构图导出为png图片或pdf文档。

名称 类型 必填 默认值 描述
exportFilename String 'OrgChart' 导出文件的文件名。
exportFileextension String 'png' 导出文件的扩展名

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;
});
类型 附带参数 描述
nodedrop.orgchart event.detail: draggedNode, dragZone, dropZone 在节点移动前于图表元素上触发。调用 event.preventDefault() 可取消本次拖放。
otherdropped.orgchart event.detail: draggedItem, dropZone 非 OrgChart 的可拖放项被放到节点上时,于图表元素上触发。
init.orgchart 无;event.target 为图表元素 图表渲染完成后触发。
show-[relation].orgchart 关联节点显示时在该节点上触发;relation 为 parent、children 或 siblings。
hide-[relation].orgchart 关联节点隐藏时在该节点上触发;relation 为 parent、children 或 siblings。

Tips

默认的展开/折叠节点功能虽然很好,但是我想禁掉它,咋办?

关于这个需求的展开讨论可以看这个问题。感谢der-robertActiveScottShaw的非常有建设性的讨论: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+