失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 树图 [ TreeMap ]

树图 [ TreeMap ]

时间:2021-04-28 10:03:21

相关推荐

树图 [ TreeMap ]

树图 [ TreeMap ]

最近项目中遇到一个特殊需求,需要将树渲染为类似于脑图的图状结构,且要兼容 IE8 ,网上找了很久,为数不多的产品要么是使用的 SVG,要么使用的 Canvas 实现,均不支持 IE8。

最终找到jquery.jOrgChart.js 虽然兼容 IE8,但原插件仅支持垂直渲染,于是花了点时间将它修改完善了一下。

修改后的插件不仅支持水平、垂直两种渲染方式,还支持自定义节点样式。

无图无真相,首先看一下效果图

github 地址:

/Blancker/TreeMap.js

因为需要兼容 IE8 这种古董级浏览器,所以插件采用 table 布局,虽然可能有点不太美观,但不得不承认,合适的才是最好的。整个插件的思想其实很简单,使用 td 存放节点,使用 colspan、rowspan 解决父子节点间的对齐问题,而层级间的连线则使用 td 的 border 表示。

我认为学习这种事,别人讲的再清楚详细都不如自己耐心理清思路学的快且扎实。所以话不多说,直接上代码。

核心代码(treeMap.js

/********** 核心代码 **********/(function($, window, document, undefined) {$.fn.treeMap = function(options) {return new initTreeMap(this, options);}$.fn.treeMap.defaults = {data : {}, // 渲染树状图的数据【必须】direction : "horizontal", // 渲染树状图的轴方向(vertical: 垂直 ; horizontal: 水平)mapClass : "treeMap",depth : -1,initLi : function (item) {return $("<li></li>").append("<span>" + item.content + "</span>");}};function initTreeMap(element, options) {this.element = $(element);this.options = $.extend({}, $.fn.treeMap.defaults, options);this.init();}initTreeMap.prototype = {init: function() {var _element = this.element;var _options = this.options;var $rootElement = $(_element); // 获取根容器元素var $container = $("<div class='" + _options.mapClass + " " + _options.direction + "'/>"); // 创建容器this.createList($rootElement, _options);if (this.options.direction == "horizontal") {this.renderForHorizontal($("#treeList").find("li:first"), $container, 0, this.options);} else {this.renderForVertical($("#treeList").find("li:first"), $container, 0, this.options);}$rootElement.append($container);},createList: function(element, options) { // 根据数据创建 ul-li 列表var $treeList = $("<ul id='treeList' style='display:none'></ul>");initList($treeList, options.data);$(element).append($treeList);function initList(treeList, jsonData) {$.each(jsonData, function(index, item) {if (item != null) {var li = options.initLi(item);if (item.childrens.length > 0) {li.append("<ul></ul>").appendTo(treeList);initList($(li).children().eq(1), item.childrens); // 递归创建子节点} else {li.appendTo(treeList);}}});}},renderForHorizontal: function(node, container, level, options) { // 递归创建节点(水平方向)var $this = this;var $childNodes = node.children("ul:first").children("li");var _rowspan = ($childNodes.length > 0) ? ($childNodes.length*4) : (2);var $table = $("<table cellpadding='0' cellspacing='0' border='0'/>");var $tbody = $("<tbody/>");var $nodeCol = $("<tr/>").addClass("node-cells");var $nodeCell = $("<td/>").addClass("node-cell").attr("rowspan", _rowspan);var $nodeContent = node.clone().children("ul,li").remove().end().html();var $nodeDiv = $("<div>").addClass("node").attr("style", (node.attr("style")) ? (node.attr("style")) : ("")).attr("title", (node.attr("title")) ? (node.attr("title")) : ("")).append($nodeContent);if ($childNodes.length > 0) {$nodeDiv.click(function() { // 展开、收起子节点var $tr = $(this).closest("tr");$(this).css('cursor','w-resize');if($tr.hasClass('contracted')){$tr.removeClass('contracted').addClass('expanded');$tr.nextAll("tr").css('visibility', '');node.removeClass('collapsed');}else{$tr.removeClass('expanded').addClass('contracted');$tr.nextAll("tr").css('visibility', 'hidden');node.addClass('collapsed');}});}$tbody.append($nodeCol.append($nodeCell.append($nodeDiv)));if ($childNodes.length > 0) {$nodeDiv.css('cursor','w-resize');if (options.depth == -1 || (level+1 < options.depth)) { var $rightLineCol = $("<tr/>");var $rightLineCell = $("<td/>").attr("rowspan", $childNodes.length*4);var $rightLine = $("<div></div>").addClass("line right");$tbody.append($rightLineCol.append($rightLineCell.append($rightLine)));var _linesCols = [];$childNodes.each(function() {var $childNode = $("<td class='node-container'/>").attr("rowspan", 2);$this.renderForHorizontal($(this), $childNode, level+1, options);var $down = $("<td>&nbsp;</td>").addClass("line down left");var $top = $("<td>&nbsp;</td>").addClass("line top left");_linesCols.push($("<tr/>").append($down).append($childNode));_linesCols.push($("<tr/>").append($top));});for (var i=0 ; i<_linesCols.length ; i++) {if (i == 0 || i == _linesCols.length-1) {_linesCols[i].find("td:first").removeClass("left");}$tbody.append(_linesCols[i]);}}}if (node.attr('class') != undefined) {var classList = node.attr('class').split(/\s+/);$.each(classList, function(index, item) {if (item == 'collapsed') {$nodeRow.nextAll('tr').css('visibility', 'hidden');$nodeRow.removeClass('expanded');$nodeRow.addClass('contracted');$nodeDiv.css('cursor','s-resize');} else {$nodeDiv.addClass(item);}});}container.append($table.append($tbody));$nodeDiv.children('a').click(function(e){console.log(e);e.stopPropagation();});},renderForVertical: function(node, container, level, options) { // 递归创建节点(垂直方向)var $this = this;var $childNodes = node.children("ul:first").children("li");var _colspan = ($childNodes.length > 0) ? ($childNodes.length*2) : (2);var $table = $("<table cellpadding='0' cellspacing='0' border='0'/>");var $tbody = $("<tbody/>");var $nodeRow = $("<tr/>").addClass("node-cells");var $nodeCell = $("<td/>").addClass("node-cell").attr("colspan", _colspan);var $nodeContent = node.clone().children("ul,li").remove().end().html();var $nodeDiv = $("<div>").addClass("node").attr("style", (node.attr("style")) ? (node.attr("style")) : ("")).attr("title", (node.attr("title")) ? (node.attr("title")) : ("")).append($nodeContent);if ($childNodes.length > 0) {$nodeDiv.click(function() { // 展开、收起子节点var $tr = $(this).closest("tr");$(this).css('cursor','s-resize');if($tr.hasClass('contracted')){$tr.removeClass('contracted').addClass('expanded');$tr.nextAll("tr").css('visibility', '');node.removeClass('collapsed');}else{$tr.removeClass('expanded').addClass('contracted');$tr.nextAll("tr").css('visibility', 'hidden');node.addClass('collapsed');}});}$tbody.append($nodeRow.append($nodeCell.append($nodeDiv)));if ($childNodes.length > 0) {$nodeDiv.css('cursor','s-resize');if (options.depth == -1 || (level+1 < options.depth)) { var $downLineRow = $("<tr/>");var $downLineCell = $("<td/>").attr("colspan", $childNodes.length*2);var $downLine = $("<div></div>").addClass("line down");$tbody.append($downLineRow.append($downLineCell.append($downLine)));var $linesRow = $("<tr/>");$childNodes.each(function() {var $left = $("<td>&nbsp;</td>").addClass("line left top");var $right = $("<td>&nbsp;</td>").addClass("line right top");$linesRow.append($left).append($right);});$linesRow.find("td:first").removeClass("top").end().find("td:last").removeClass("top");$tbody.append($linesRow);var $childNodesRow = $("<tr/>");$childNodes.each(function() {var $td = $("<td class='node-container'/>");$td.attr("colspan", 2);$this.renderForVertical($(this), $td, level+1, options);$childNodesRow.append($td);});$tbody.append($childNodesRow);}}if (node.attr('class') != undefined) {var classList = node.attr('class').split(/\s+/);$.each(classList, function(index, item) {if (item == 'collapsed') {$nodeRow.nextAll('tr').css('visibility', 'hidden');$nodeRow.removeClass('expanded');$nodeRow.addClass('contracted');$nodeDiv.css('cursor','s-resize');} else {$nodeDiv.addClass(item);}});}container.append($table.append($tbody));$nodeDiv.children('a').click(function(e){console.log(e);e.stopPropagation();});}};})(jQuery, window, document);

默认样式 (treeMap.css

/* Basic styling *//* node cell */.treeMap td {text-align: center;vertical-align: middle;padding: 0;}.treeMap.vertical td {vertical-align: top;}/* The node */.treeMap .node {margin: 4px 0px;padding: 12px;background-color: #35363B;font-size: 12px;color: #FFFFFF;border-radius: 4px;display: inline-block;}.treeMap.horizontal .node {white-space: nowrap;}.treeMap.vertical .node {margin: 0px 4px;}.treeMap .node a {color: #FFFFFF;text-decoration: none;}/* Draw the lines */.treeMap.horizontal .line {height: 4px;width: 20px;}.treeMap.horizontal .right, .treeMap.vertical .down {background-color: black;margin: 0px auto;}.treeMap.horizontal .top { border-top: 2px solid black; }.treeMap.horizontal .down { border-bottom: 2px solid black; }.treeMap.horizontal .left { border-left: 4px solid black; }.treeMap.vertical .line {height: 20px;width: 4px;}.treeMap.vertical .down {background-color: black;margin: 0px auto;}.treeMap.vertical .top { border-top: 4px solid black; }.treeMap.vertical .right { border-left: 2px solid black; }.treeMap.vertical .left { border-right: 2px solid black; }

demo (demo.html

<!DOCTYPE html><html><head><meta charset="utf-8"><title>TreeMap Demo</title><link rel="stylesheet" type="text/css" href="./css/treeMap.css"/></head><body><div id='treeMap-horizontal'></div><br /><hr /><br /><div id='treeMap-vertical'></div><script src="./js/jquery.min.js" type="text/javascript" charset="utf-8"></script><script src="./js/treeMap.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">var treeJson = [{"id" : "1", "text" : "父节点", "parentId" : "0","childrens" : [{ "id" : "2", "text" : "子节点一", "parentId" : "1", "childrens" : [] },{ "id" : "3", "text" : "子节点二", "parentId" : "1","childrens" : [{ "id" : "5", "text" : "孙子节点一", "parentId" : "3", "childrens" : [] },{ "id" : "6", "text" : "孙子节点二", "parentId" : "3", "childrens" : [] }]},{"id" : "4", "text" : "子节点三", "parentId" : "1","childrens" : [ { "id" : "7", "text" : "孙子节点三", "parentId" : "4", "childrens" : [] } ]}]}];$("#treeMap-horizontal").treeMap({data : treeJson, // 渲染树状图的数据【必须】initLi : function (item) {var liStyle = "", liTitle = "";if (item.id == 2) {liStyle = "background-color:rgb(255,0,0);";liTitle = "已完成";} else if(item.id == 5) {liStyle = "background-color:rgb(0,255,0);";liTitle = "进行中";}return $("<li style='" + liStyle + "' title='" + liTitle + "'></li>").append("<span>" + item.text + "</span>");}});$("#treeMap-vertical").treeMap({data : treeJson, // 渲染树状图的数据【必须】direction : "vertical", // 渲染树状图的轴方向(vertical: 垂直 ; horizontal: 水平)initLi : function (item) {var liStyle = "", liTitle = "";if (item.id == 2) {liStyle = "background-color:rgb(255,0,0);";liTitle = "已完成";} else if(item.id == 5) {liStyle = "background-color:rgb(0,255,0);";liTitle = "进行中";}return $("<li style='" + liStyle + "' title='" + liTitle + "'></li>").append("<span>" + item.text + "</span>");}});function toView(id) {alert(id);}</script></body></html>

如果觉得《树图 [ TreeMap ]》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。