解析json输出思维导图
1说明
i、js用的是raphael(绘制图形),jquery(主要get到json)
ii、设计初衷是做后台管理的导航地图,也基本实现这个功能
iii、json里面主要2个key,一个是name,一个是children,如果想要额外功能,比如跳转指定网址,请加参数,并在click方法内添加
2显示效果
3传入json
{ "name": "a", "children": [ { "name": "a1", "children": [ { "name": "a11", "children": [ { "name": "a111" }, { "name": "a112" }, { "name": "a117", "children": [ { "name": "a1171" }, { "name": "a1172" }, { "name": "a1173" } ] } ] }, { "name": "a12" } ] } , { "name": "a2", "children": [ { "name": "a21" }, { "name": "a22" , "children": [ { "name": "a221" }, { "name": "a222" } ] } ] } , { "name": "a3", "children": [ { "name": "a31" } ] } , { "name": "a4", "children": [ { "name": "a41" }, { "name": "a42" } ] } ] }
4下面是代码
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Raphael Test</title> </head> <body> <div id="my-canvas" style="width:140px;padding:0px;margin:0px;"></div> <span id="ruler" style="visibility: hidden; white-space: nowrap; font-size: 10px; "></span> <!--some html doms--> <!--some scripts--> <script type="text/javascript" src="raphael.js"></script> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> String.prototype.visualLength = function() { var ruler = $("#ruler"); ruler.text(this); return ruler[0].offsetWidth; } ; var mindmap = function(id, width, height, data) { var leftY = 0; //左侧初始高度(系统自动计算) var rightY = 0; //右侧初始高度 (系统自动计算) var unitWidth = 50; //每个文本的宽度(手工改) var unitHeight = 16; //每个文本的高度(手工改) var xAdd = 230; //x坐标偏移量(手工改)默认中心位置在(0,0),只能显示1/4图片,就是x,-y象限,需要把图片往右下方移动才能看到全貌 var yAdd = 00; //y坐标偏移量(手工改) var xRate = 70; //x比例系数(手工改)用于放大内容 var yRate = 50; //y比例系数(手工改) var lineColor = ["yellow", "FF00AC", "green", "red", "F3B1A0"]; //线条颜色 var colorIndex = 0; //对象1继承对象2的内容 var extend = function(destination, source) { for (var property in source) destination[property] = source[property]; return destination; }; //计算孩子节点的数量 //children是孩子部分 //size是内部数量 //isRight=true表示在右边 //level表示第几层级 //thick表示深度 var countChildrenSize = function(data, level, isRight, depth) { var size = 0; //有几个孩子 var leftSize = 0; //左侧总高度 var rightSize = 0; //右侧总高度 var thick = 0; //深度 var leftThick = 0; //左侧总高度 var rightThick = 0; //右侧总高度 if (data["children"] != null && data["children"].length > 0) {//如果没有孩子节点,则自己设为0,返回0 for (var i = 0; i < data["children"].length; i++) { var right = isRight != null ? isRight : (i % 2 == 0); var count = countChildrenSize(data["children"][i], level + 1, right, depth + 1); size += count.size; if (thick < count.thick) { thick = count.thick; }; if (right) { rightSize += count.size; if (rightThick < thick) { rightThick = thick; }; } else { leftSize += count.size; if (leftThick < thick) { leftThick = thick; }; } } thick++; } else { size = 1; thick = 1; } extend(data, { depth : depth, size : size, level : level, thick : thick }); if (isRight != null) { data.isRight = isRight; }; return { size : size, thick : thick, rightSize : rightSize, leftSize : leftSize, rightThick : rightThick, leftThick : leftThick, }; }; //计算位置,json,左边深度,右边深度 var countPos = function(data, rightThick, leftThick) { var width; var height; if (data["children"] != null && data["children"].length > 0) { var sumHeight = 0; for (var i = 0; i < data["children"].length; i++) { var pos = countPos(data["children"][i], rightThick, leftThick); sumHeight += pos.height; } height = sumHeight / data["children"].length; } else { if (data.isRight) { rightY = rightY + 1; height = rightY; } else { leftY = leftY + 1; height = leftY; } } if (data.isRight == null) { width = 0; } else if (data.isRight) { width = data.depth; } else { width = -data.depth; } ; var pos = { width : width, height : height }; extend(data, pos); return pos; }; //数据,绘图,父节点 var draw = function(data, paper, parentData) { if (parentData != null) {//线条颜色 data.color = parentData.color == null ? lineColor[colorIndex++] : parentData.color; } if (data["children"] != null && data["children"].length > 0) { for (var i = 0; i < data["children"].length; i++) { draw(data["children"][i], paper, data); } } var posX = xAdd + xRate * data.width; var posY = yAdd + yRate * data.height; //和上级的连接曲线 if (parentData != null) { var _posX = xAdd + xRate * parentData.width;//父节点的x var _posY = yAdd + yRate * parentData.height;//父节点的y var start = data.isRight ? { x : posX, y : posY + unitHeight / 2 } : { x : posX + unitWidth, y : posY + unitHeight / 2 };//起始点 var end = data.isRight ? { x : _posX + unitWidth, y : _posY + unitHeight / 2 } : { x : _posX, y : _posY + unitHeight / 2 };//结束点 var cut1 = { x : end.x, y : start.y }; var cut2 = { x : start.x, y : end.y }; //曲线连接 paper.path("M" + start.x + " " + start.y + " C" + cut1.x + " " + cut1.y + " " + cut2.x + " " + cut2.y + " " + end.x + " " + end.y).attr('stroke', data.color); //直线连接 //paper.path("M"+(posX+unitWidth)+" "+(posY+unitHeight/2)+"L"+(_posX)+" "+(_posY+unitHeight/2)).attr("stroke",data.color); //下划线 paper.path("M" + posX + " " + (posY + unitHeight / 2) + "L" + (posX + unitWidth) + " " + (posY + unitHeight / 2)).attr("stroke", data.color); }else{//第一个主题,加框 paper.rect(posX,posY- unitHeight / 2,unitWidth,unitHeight,2); }; //paper.rect((xAdd + xRate * data.width),( yAdd + yRate * data.height),(xAdd + xRate * data.width+unitHeight),( yAdd + yRate * data.height+unitHeight),10).attr("fill","yellow"); var len = data.name.visualLength(); //主体文本 var text = paper.text(xAdd + xRate * data.width+(unitWidth-len)/2, yAdd + yRate * data.height, data.name); text.attr({ "fill" : "dodgerblue", "font-size" : "10px", "text-anchor" : "start", }); text.click(function() { alert(data.name); window.open('http://www.baidu.com');//可以用作导航,打开页面 }); }; //初始化图形 var init = function(data) { var paper = Raphael(id, width, height); //计算孩子辅助数据 var count = countChildrenSize(data, 1, null, 0); console.info(count); var difference = Math.floor(Math.abs(count.rightSize - count.leftSize) / 2); //左右起始高度差 if (count.rightSize > count.leftSize) {//初始化第一个位置 leftY += difference; }; //计算叶子相对位置 countPos(data, count.rightThick, count.leftThick); draw(data, paper); console.info(JSON.stringify(data)); }; //at last init(data); }; $.ajax({ url : "a.json", data : { t : new Date().getTime() }, dataType : "json", success : function(data) { mindmap("my-canvas", 800, 500, data); } }); </script> </body> </html>