解析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>

 

posted @ 2018-03-08 10:48  baliure  阅读(3051)  评论(0编辑  收藏  举报