文档章节

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

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

效果图:

输入图片说明

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
强大的矢量图形库:Raphael JS 中文帮助文档及教程

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

李朝强
2013/10/24
0
1
利用多叉树实现Ext JS中的无限级树形菜单(一种构建多级有序树形结构JSON的方法)

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

Alex_曰生
2014/12/01
0
2
如何使用纯CSS3来生成家谱(family tree)

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

gbin1
2012/07/30
0
0
JavaScript 二叉搜索树以及实现翻转二叉树

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

CaiJinyc
06/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

emoji

前言:随着iOS系统版本的升级,对原生emoji表情的支持也越来越丰富。emoji表情是unicode码中为表情符号设计的一组编码,当然,还有独立于unicode的另一套编码SBUnicode,在OS系统中,这两种编...

HeroHY
15分钟前
0
0
rabbitmq学习(二)

生产者消费者初级案列 ChannelUtils package com.hensemlee.rabbitmq;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.Connecti......

hensemlee
24分钟前
0
0
MarkDown入门简介

Markdown是一种可以使用普通文本编辑器编写的标记语言,通过类似HTML的标记语法,它可以使普通文本内容具有一定的格式。Markdown的语法简洁明了、学习容易,而且功能比纯文本更强,因此有很多...

一零贰IV
28分钟前
0
0
druid配置db2参考记录

Driver Name:COM.ibm.db2.jdbc.app.DB2 Driver Type 4 Driver URL Pattern:jdbc:db2://ServerIP:50000/databasename ${driverClassName} 这个参数没有在spring相关的properties文件中配置 ......

tonyfox
32分钟前
0
0
用户体验要素——以用户为设计中心

一、用户体验是什么 产品会与外界发生联系,人们如何去使用产品,人们使用产品无非解决两种问题,一,提高效率;二娱乐。而用户体验兼顾着功能和界面两个方面,为的是“提高人们的工作效率”...

铸剑为犁413
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部