文档章节

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

kindcao
 kindcao
发布于 2017/09/06 16:51
字数 757
阅读 150
收藏 1
点赞 0
评论 0

效果图:

输入图片说明

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 二叉搜索树以及实现翻转二叉树

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

CaiJinyc ⋅ 06/10 ⋅ 0

深入框架本源系列 —— Virtual Dom

该系列会逐步更新,完整的讲解目前主流框架中底层相通的技术,接下来的代码内容都会更新在 这里 为什么需要 Virtual Dom 众所周知,操作 DOM 是很耗费性能的一件事情,既然如此,我们可以考虑...

夕阳 ⋅ 06/02 ⋅ 0

37互娱前端校招笔试(2019提前批)

选择题 -7的二进制补码是多少?(牛客题) RSA, SHA, DES, BASE64中哪个是不可逆的? 计算机软件可以分为系统软件和应用软件,请问系统软件的核心是什么? 线性表(7, 34, 55, 25, 64, 46, 2...

求职小小菜鸡 ⋅ 06/06 ⋅ 0

JavaScript 算法与数据结构 - javascript-algorithms

javascript-algorithms 包含了多种基于 JavaScript 的算法与数据结构。 每种算法和数据结构都有自己的 README 并提供相关说明以及进一步阅读和 YouTube 视频。 数据结构 数据结构是在计算机中...

匿名 ⋅ 05/31 ⋅ 0

JavaScript零基础入门——(十)JavaScript的DOM基础

JavaScript零基础入门——(十)JavaScript的DOM基础 欢迎大家回到我们的JavaScript零基础入门,上一节课,我们了解了JavaScript中的函数,这一节课,我们来了解一下JavaScript的DOM。 第一节...

JandenMa ⋅ 昨天 ⋅ 0

面向对象,更适合JavaScript

面向对象程序设计是软件开发中一个很庞大很复杂的话题,它并不是仅仅学会类、继承、封装、多态这些面向对象编程语法元素就表示掌握的,这些语法元素只是实现面向对象程序的工具, 就像砖块、...

陈宏鸿 ⋅ 05/07 ⋅ 0

使用Javascript来实现的超炫组织结构图(Organization Chart)

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

gbin1 ⋅ 2011/06/29 ⋅ 3

再谈 load 与 DOMContentLoaded

本文首发在github,感兴趣请点击此处 window 的 onload 事件对于前端童鞋来说肯定是熟的不能再熟了,相信大家在刚入门时,见的最多的可能就是 load 事件了。load 事件接触多了,大家就会接触...

lucefer ⋅ 06/21 ⋅ 0

JS原型与原型链终极详解_proto_、prototype及constructor

一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object ,Function 是JS自带的函数对象。下面举例说明 function f1(){}; var f2 = functi...

黑魔法 ⋅ 04/24 ⋅ 0

学习Javascript的8张思维导图

分别归类为:  javascript变量  javascript运算符  javascript数组  javascript流程语句  javascript字符串函数  javascript函数基础  javascript基础DOM操作  javascript正则表达式...

thinkyoung ⋅ 2014/09/23 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

关于线程的创建

转自自己的笔记: http://note.youdao.com/noteshare?id=87584d4874acdeaf4aa027bdc9cb7324&sub=B49E8956E145476191C3FD1E4AB40DFA 1.创建线程的方法 Java使用Thread类代表线程,所有的线程对......

MarinJ_Shao ⋅ 28分钟前 ⋅ 0

工厂模式学习

1. 参考资料 工厂模式-伯乐在线 三种工厂-思否 深入理解工厂模式 2. 知识点理解 2.1 java三种工厂 简单工厂 工厂模式 抽象工厂 2.2 异同点 逐级复杂 简单工厂通过构造时传入的标识来生产产品...

liuyan_lc ⋅ 40分钟前 ⋅ 0

Java NIO

1.目录 Java IO的历史 Java NIO之Channel Java NIO之Buffer Java NIO之Selector Java NIO之文件处理 Java NIO之Charset Java 可扩展IO 2.简介 “IO的历史”讲述了Java IO API从开始到现在的发...

士别三日 ⋅ 44分钟前 ⋅ 0

[Err] ORA-24344: success with compilation error

从txt文本复制出创建function的脚本,直接执行,然后报错:[Err] ORA-24344: success with compilation error。 突然发现脚本的关键字,居然不是高亮显示。 然后我把脚本前面的空格去掉,执行...

wenzhizhon ⋅ 53分钟前 ⋅ 0

Spring Security授权过程

前言 本文是接上一章Spring Security认证过程进一步分析Spring Security用户名密码登录授权是如何实现得; 类图 调试过程 使用debug方式启动https://github.com/longfeizheng/logback该项目,...

hutaishi ⋅ 今天 ⋅ 0

HAProxy基于KeepAlived实现Web高可用及动静分离

前言 软件负载均衡一般通过两种方式来实现: 基于操作系统的软负载实现 基于第三方应用的软负载实现 LVS是基于Linux操作系统实现的一种软负载,而HAProxy则是基于第三方应用实现的软负载。 ...

寰宇01 ⋅ 今天 ⋅ 0

微软自研处理器的小动作:已经开始移植其他平台的工具链

微软将 Windows 10 、Linux 以及工具链如 C/C++ 和 .NET Core 运行时库、Visual C++ 2017 命令行工具、RyuJIT 编辑器等移植到其自主研发的处理器架构 E2。微软还移植了广泛使用的 LLVM C/C++...

linux-tao ⋅ 今天 ⋅ 0

JS常见this指代总结

1. dom0级事件处理程序的回调函数内 2. dom2级事件处理程序的回调函数内 3. setTimeout 4. setInterval var test = { testfn: function () { console.log(this); }};...

静默行 ⋅ 今天 ⋅ 0

泛型的基本原理

泛型是 JDK1.5 的一个新特性,其实就是一个『语法糖』,本质上就是编译器为了提供更好的可读性而提供的一种小「手段」,虚拟机层面是不存在所谓『泛型』的概念的。 在我看来,『泛型』的存在...

沧海一刀 ⋅ 今天 ⋅ 0

学好Java只需要做到这8点,年薪30W很简单!文末福利赠送!

前言: 大道至简,所以扎实有用的方法,其实都是很简单的,难在踏踏实实的执行过程。今天为大家介绍的就是Java学习的8个看起来非常简单的方法,快学起来吧。 为什么要学习Java? Java是目前最...

java高级架构牛人 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部