文档章节

Raphael JS - 组织结构图/层次结构图/多叉树图

kindcao
 kindcao
发布于 2017/09/06 16:51
字数 757
阅读 170
收藏 1

效果图:

输入图片说明

raphael.html 源码

<html>
<head>
</head>
<body>
	<center>
		<h1>Raphael JS - 组织结构图/层次结构图/多叉树图</h1>
	</center>
</body>
<script src="https://cdn.bootcss.com/raphael/2.2.7/raphael.js"></script>
<script src="./raphael-orgchart.js"></script>
<script>
    var data = [];
    data.push({
        "id" : "0",
        "name" : "root",
        "parentId" : -1,
        "txt1" : "txt1-root"

    });
    data.push({
        "id" : "1",
        "name" : "name1",
        "parentId" : 0,
        "txt1" : "txt1-name1"
    });
    data.push({
        "id" : "2",
        "name" : "name2",
        "parentId" : 0,
        "txt1" : "txt1-name2"
    });
    data.push({
        "id" : "3",
        "name" : "name3",
        "parentId" : 0,
        "txt1" : "txt1-name3"
    });
    data.push({
        "id" : "4",
        "name" : "name4",
        "parentId" : 1,
        "txt1" : "txt1-name4"
    });
    data.push({
        "id" : "5",
        "name" : "name5",
        "parentId" : 1,
        "txt1" : "txt1-name5"
    });
    data.push({
        "id" : "6",
        "name" : "name6",
        "parentId" : 1,
        "txt1" : "txt1-name6"
    });
    data.push({
        "id" : "7",
        "name" : "name7",
        "parentId" : 3,
        "txt1" : "txt1-name7"
    });
    data.push({
        "id" : "8",
        "name" : "name8",
        "parentId" : 3,
        "txt1" : "txt1-name8"
    });
    data.push({
        "id" : "9",
        "name" : "name9",
        "parentId" : 5,
        "txt1" : "txt1-name9"
    });
    data.push({
        "id" : "10",
        "name" : "name10",
        "parentId" : 5,
        "txt1" : "txt1-name10"
    });
    data.push({
        "id" : "11",
        "name" : "name11",
        "parentId" : 6,
        "txt1" : "txt1-name11"
    });
    data.push({
        "id" : "12",
        "name" : "name12",
        "parentId" : 6,
        "txt1" : "txt1-name12"
    });
    data.push({
        "id" : "13",
        "name" : "name13",
        "parentId" : 6,
        "txt1" : "txt1-name13"
    });

    data.push({
        "id" : "14",
        "name" : "name14",
        "parentId" : 7,
        "txt1" : "txt1-name14"
    });

    data.push({
        "id" : "15",
        "name" : "name15",
        "parentId" : 7,
        "txt1" : "txt1-name15"
    });

    data.push({
        "id" : "16",
        "name" : "name16",
        "parentId" : 7,
        "txt1" : "txt1-name16"
    });

   var chart = new orgchart(5, 30, data);
    chart.drawChart();
</script>
</html>

raphael-orgchart.js 源码

/**
 * Raphael JS - 组织结构图/层次结构图/多叉树图
 */

orgchart = function(Px, Py, D) {
	if (!Array.isArray(D)) {
		console.log("Need array args!");
		return;
	}
	var data = D;

	// 参考原点坐标
	var X = Px;
	var Y = Py;

	// 最大层数/行数
	var maxRowNum = 0;
	// 最大列数
	var maxColNum = 0;
	// 单元格宽度
	var cellW = 100;
	// 单元格高度
	var cellH = 50;
	// 水平间距/列距
	var hSpace = 50;
	// 垂直间距/行距
	var vSpace = 50;
	// 画布对象
	var paper;
	// 画布宽度
	var paperW = 0;
	// 画布高度
	var paperH = 0;

	this.drawChart = function init() {
		calc();
		draw();
	}

	//
	function calc() {
		// 统计不重复的父节点总个数
		var _rowSet = new Set();
		for (var i = 0; i < data.length; i++) {
			data[i]["xy"] = {
				"x" : X,
				"y" : Y
			};
			//
			_rowSet.add(data[i].parentId);
		}
		//
		maxRowNum = _rowSet.size;
		// 节点总数-(父节点总数-1); 1--根节点没有父节点,排除
		maxColNum = data.length - (_rowSet.size - 1);
		paperW = maxColNum * (cellW + hSpace);
		paperH = maxRowNum * (cellH + vSpace);
		paper = new Raphael(X, Y, paperW, paperH);
		//
		var rootObj = findRoot();
		if (rootObj != null) {
			calcXY(rootObj, 0);
			calcParentXY(rootObj);
		}
		// console.log("paperW= " + paperW + " paperH= " + paperH + " maxRowNum=
		// " + maxRowNum + " maxColNum= " + maxColNum)
	}

	function calcXY(obj, level) {
		level++;
		var childrenArr = getChildren(obj);
		for (var i = 0; i < childrenArr.length; i++) {
			//
			if (i == 0) {
				childrenArr[i].xy.x = obj.xy.x;
			} else {
				var offsetX = 0;
				var childrenArr2 = getChildren(childrenArr[i - 1]);
				if (childrenArr2.length > 0) {
					offsetX = childrenArr2[childrenArr2.length - 1].xy.x;
				} else {
					offsetX = childrenArr[i - 1].xy.x;
				}
				childrenArr[i].xy.x = offsetX + (cellW + hSpace);
			}
			childrenArr[i].xy.y += (cellH + vSpace) * level;
			obj.xy.x = childrenArr[i].xy.x

			//          
			calcXY(childrenArr[i], level);
		}
		// console.log(" | " + level + " calcXY" + obj.name + " " + obj.xy.x + "
		// " + obj.xy.y)
	}

	function calcParentXY(obj) {
		var childrenArr = getChildren(obj);
		for (var i = 0; i < childrenArr.length; i++) {
			calcParentXY(childrenArr[i]);
		}

		if (childrenArr.length > 0) {
			if (childrenArr.length % 2 == 0) {
				obj.xy.x = (childrenArr[0].xy.x + childrenArr[childrenArr.length - 1].xy.x) / 2;
			} else {
				obj.xy.x = childrenArr[Math.floor(childrenArr.length / 2)].xy.x;
			}
		}
	}

	function findRoot() {
		for (var i = 0; i < data.length; i++) {
			if (data[i].parentId == -1) {
				return data[i];
			}
		}
		return null;
	}

	function getChildren(obj) {
		var childrenArr = [];
		for (var i = 0; i < data.length; i++) {
			if (data[i].parentId == obj.id) {
				childrenArr.push(data[i]);
			}
		}
		return childrenArr;
	}

	function draw() {
		for (var i = 0; i < data.length; i++) {
			drawRect(data[i]);
			//
			var childrenArr = getChildren(data[i]);
			for (var j = 0; j < childrenArr.length; j++) {
				drawLine(data[i], childrenArr[j], j == 0 ? true : false)
			}
		}
	}

	function drawLine(parentObj, obj, isFirst) {
		//
		var Pp_X = parentObj.xy.x + cellW / 2;
		var Pp_Y1 = parentObj.xy.y + cellH;
		var P_Y = parentObj.xy.y + cellH + vSpace / 2;
		//
		var Pc_X = obj.xy.x + cellW / 2;
		var Pc_Y1 = obj.xy.y;

		//
		var linePathStr = " M" + Pc_X + " " + P_Y + "L" + Pp_X + " " + P_Y
				+ " M" + Pc_X + " " + P_Y + "L" + Pc_X + " " + Pc_Y1;
		if (isFirst) {
			linePathStr = "M" + Pp_X + " " + Pp_Y1 + "L" + Pp_X + " " + P_Y
					+ linePathStr;
		}
		//
		var line = paper.path(linePathStr);
		line.attr({
			stroke : "#000"
		});

		//
		var txt = paper.text(Pc_X, (obj.xy.y + P_Y) / 2, obj.txt1);
		txt.attr({
			fill : "#4169E1",
			"font-size" : 10
		});
	}

	function drawRect(obj) {
		//
		var rect = paper.rect(obj.xy.x, obj.xy.y, cellW, cellH, 10);
		rect.mousemove(function() {
			this.attr("fill", "#ADFF2F");
		});
		rect.mouseout(function() {
			this.attr("fill", "#fff");
		});
		rect.attr({
			title : obj.name
		});

		//
		var txt = paper.text(obj.xy.x + cellW / 2, obj.xy.y + cellH / 2,
				obj.name);
	}
}

© 著作权归作者所有

共有 人打赏支持
kindcao
粉丝 5
博文 16
码字总数 5939
作品 0
深圳
高级程序员
使用Javascript来实现的超炫组织结构图(Organization Chart)

最近有个内部项目需要使用组织结构图(organization chart), 寻找了一些开源的项目及其类库,发现竟然没有现成的JS类库可以使用,找到一些简单的JS实现,不过界面及其操作及其简单,不过功夫...

gbin1
2011/06/29
0
3
利用多叉树实现Ext JS中的无限级树形菜单(一种构建多级有序树形结构JSON的方法)

一、问题研究的背景和意义 目前在Web应用程序开发领域,Ext JS框架已经逐渐被广泛使用,它是富客户端开发中出类拔萃的框架之一。在Ext的UI控件中,树形控件无疑是最为常用的控件之一,它用来...

Alex_曰生
2014/12/01
0
2
强大的矢量图形库:Raphael JS 中文帮助文档及教程

Raphael 是一个用于在网页中绘制矢量图形的 Javascript 库。它使用 SVG W3C 推荐标准和 VML 作为创建图形的基础,你可以通过 JavaScript 操作 DOM 来轻松创建出各种复杂的柱状图、饼图、曲线...

李朝强
2013/10/24
0
1
JavaScript 二叉搜索树以及实现翻转二叉树

本文包括:二叉搜索树(创建、遍历、搜索、插入等)、JavaScript 实现翻转二叉树 欢迎关注我的:个人博客、Github。 什么是二叉树? 二叉树的定义:二叉树的每个结点至多只有二棵子树(不存在...

CaiJinyc
06/10
0
0
如何使用纯CSS3来生成家谱(family tree)

日期:2012-7-28 来源:GBin1.com 今天我们将要介绍的是如何在不使用Flash和JavaScript的 情况下,用纯CSS来完成一个可组织数据或者家谱。这里使用一个非常简单的标签 - 嵌套列表li。 其中伪...

gbin1
2012/07/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

[雪峰磁针石博客]python3快速入门教程1 turtle绘图-2函数

菲波那契序列: >>> # Fibonacci series:... # the sum of two elements defines the next... a, b = 0, 1>>> while b < 10:... print(b)... a, b = b, a+b...112......

python测试开发人工智能安全
今天
0
0
java环境变量配置最正确的方式

原贴:https://blog.csdn.net/qq_40007997/article/details/79784711,十分详细,亲测有效

kitty1116
今天
0
0
49.Nginx防盗链 访问控制 解析php相关 代理服务器

12.13 Nginx防盗链 12.14 Nginx访问控制 12.15 Nginx解析php相关配置(502的问题) 12.16 Nginx代理 扩展 502问题汇总 http://ask.apelearn.com/question/9109 location优先级 http://blog....

王鑫linux
今天
1
0
Nginx防盗链、访问控制、解析php相关配置、Nginx代理

一、Nginx防盗链 1. 编辑虚拟主机配置文件 vim /usr/local/nginx/conf/vhost/test.com.conf 2. 在配置文件中添加如下的内容 { expires 7d; valid_referers none blocked server_names *.tes......

芬野de博客
今天
0
0
spring EL 和资源调用

资源调用 import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.PropertySource;import org.springframework.core.io.Resource;......

Canaan_
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部