Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

d3js 画出流程图+哈夫曼方法计算节点高亮显示 #4

Open
zhoupj opened this issue Jul 27, 2016 · 1 comment
Open

d3js 画出流程图+哈夫曼方法计算节点高亮显示 #4

zhoupj opened this issue Jul 27, 2016 · 1 comment

Comments

@zhoupj
Copy link
Owner

zhoupj commented Jul 27, 2016

  • 位置固定显示
  • 适合用于流程图
    data 类似如下:
/*状态使用了哈夫曼编码,数字不要随便更改**/
    getTreeData: function(){
        var   treeData={
            order:1,
            value:"已创建",
            children:[{
                order:2,
                value:"开发中",
                msg:"开发完成后,发起‘申请合并’并等待所有开发都提交‘申请合并’后才进行下一步",
                children:[{
                        order:4,
                        value:"已申请合并",
                        children:[{
                            order:8,
                            value:"测试确认中",
                            msg:"只有测试者可以操作,测试者确认所有文件改动都是ok后,进行到下一步,否则可以点击回滚到开发中",
                            children:[{
                                order:16,
                                value:"已确认",
                                msg:"所有测试者确认完毕后,系统发起'合并'操作",
                                children:[{  order:33,
                                            value:"合并失败",
                                            msg:"合并失败,工单状态可以回滚到开发中",
                                    },{
                                    order:32,
                                    value:"已合并",
                                    children:[{
                                        order:64,
                                        value:"发布中",
                                        children:[{order:129,
                                                value:"发布失败",
                                                msg:"可以进行'重新发布'操作"
                                            },{
                                            order:128,
                                            value:"已发布",
                                            children:[{
                                                order:256,
                                                value:"结束",
                                            }]
                                        }]
                                    }/**,{
                                          order:65,
                                            value:"已废弃",
                                            children:[{
                                                order:131,
                                                value:"结束",
                                            }]  


                                    }**/]
                                }]
                            }]
                        }]
               },{
                    order:5,
                    value:"已废弃",
                    children:[{
                        order:11,
                        value:"结束",
                    }]  
                }]
            },]
      }

code如下:

/**
          流程处理方法
   **/
   D3Tree(treeData,statusValue){
        // Calculate total nodes, max label length
        var totalNodes = 0;
        var maxLabelLength = 0;

        // panning variables
        var panSpeed = 200;
        var panBoundary = 20; // Within 20px from edges will pan when dragging.
        // Misc. variables
        var i = 0;
        var duration = 750;
        var root;

        // size of the diagram
        var viewerWidth = 800
        var viewerHeight =200;
        var fullScreenFlag=0;
        var dragStarted=null;
        var  domNode=null;
        var nodes;

        var tree = d3.layout.tree()
            .size([viewerHeight, viewerWidth]);

        // define a d3 diagonal projection for use by the node paths later on.
        var diagonal = d3.svg.diagonal()
            .projection(function(d) {
                return [d.y, d.x];
            });

        var baseSvg;

        //clear
        d3.select("#tree-container").html("");
        //

        baseSvg = d3.select("#tree-container").append("svg")
            .attr("width", viewerWidth)
            .attr("height", viewerHeight)
            .attr("class", "overlay")
            //.call(zoomListener);

        // A recursive helper function for performing some setup by walking through all nodes

        function visit(parent, visitFn, childrenFn) {
            if (!parent) return;

            visitFn(parent);

            var children = childrenFn(parent);
            if (children) {
                var count = children.length;
                for (var i = 0; i < count; i++) {
                    visit(children[i], visitFn, childrenFn);
                }
            }
        }

        // Call visit function to establish maxLabelLength
        visit(treeData, function(d) {
            totalNodes++;
            maxLabelLength = Math.max(d.value.length, maxLabelLength);

            }, function(d) {
                return d.children && d.children.length > 0 ? d.children : null;
        });


        // Define the zoom function for the zoomable tree

        function zoom() {
            svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }

        // define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents
        var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom);


        // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children.

        function centerNode(source) {

            var  scale = zoomListener.scale();
             var   x = -source.y0;
             var   y = -source.x0;
                x = x * scale + viewerWidth / 8+20;
                y = y * scale + viewerHeight / 2+25;
                d3.select('g').transition()
                    .duration(duration)
                    .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
                zoomListener.scale(scale);
                zoomListener.translate([x, y]);


        }



      /*******************添加矩形圆角背景边框,样式**************************/
            var toottipWidth=200;
            var tooltip = d3.select("body")
                    .append("div")
                    .attr("class","tooltip2")
                    .style("opacity",0.0).style("left", "-500px")
                    .style("top", "-200px").style("z-index",'2')
                    .style("width",toottipWidth);

        var currentNode=null;
        function update(source) {
            // Compute the new height, function counts total children of root node and sets tree height accordingly.
            // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed
            // This makes the layout more consistent.
            var levelWidth = [1];
            var childCount = function(level, n) {

                if (n.children && n.children.length > 0) {
                    if (levelWidth.length <= level + 1) levelWidth.push(0);

                    levelWidth[level + 1] += n.children.length;
                    n.children.forEach(function(d) {
                        childCount(level + 1, d);
                    });
                }
            };
            childCount(0, root);
            var newHeight = d3.max(levelWidth) * 90; // 25 pixels per line  
            tree = tree.size([newHeight, viewerWidth]);

            // Compute the new tree layout.
            var nodes = tree.nodes(root).reverse(),
                links = tree.links(nodes);

            // Set widths between levels based on maxLabelLength.
            nodes.forEach(function(d) {
               // d.y = (d.depth * (maxLabelLength * 10)); //maxLabelLength * 10px
                // alternatively to keep a fixed scale one can set a fixed depth per level
                // Normalize for fixed-depth by commenting out below line
                d.y = (d.depth * 80); //500px per level.
            });

            // Update the nodes…
           var  node = svgGroup.selectAll("g.node")
                .data(nodes, function(d) {
                    return d.id || (d.id = ++i);
                });

            // Enter any new nodes at the parent's previous position.
            var nodeEnter = node.enter().append("g")
                //.call(dragListener)
                .attr("class", "node")
                .attr("transform", function(d) {
                    return "translate(" + source.y0 + "," + source.x0 + ")";
                })//.on("click", click);

              /*******************以上为添加浮层,样式*****************************/


            nodeEnter.append("circle")
                .attr('class', 'nodeCircle')
                .attr("r", 0)
                .style("fill", function(d) {
                    return d.children || d._children ? "lightsteelblue" : "#fff";
                })



            nodeEnter.append("text")
                .attr("x", function(d) {
                    return d.children || d._children ? -15 : 15;
                })
                .attr("dy", ".35em")
                .attr('class', 'nodeText')
                .attr("text-anchor", function(d) {
                    return d.children || d._children ? "middle" : "start";
                })
                .text(function(d) {
                    return d.value;
                })
                .style("fill-opacity", 10);



            // Update the text to reflect whether node has children or not.
            node.select('text')
                .attr("x", function(d) {
                    return d.children || d._children ? 0 : 0;
                })
                 .attr("y", function(d) {
                    return  20;
                })
                .attr("text-anchor", function(d) {
                    return d.children || d._children ? "middle" : "middle";
                })
                .text(function(d) {
                    return d.value;
                });



            // Change the circle fill depending on whether it has children and is collapsed
            node.select("circle.nodeCircle")
                .attr("r", 10)
                .style("fill", function(d) {



                    if(d.order <=statusValue ){
                        if(d.order==statusValue){
                            currentNode=this;
                        }

                        if(statusValue.toString(2).indexOf(d.order.toString(2),0)==0){
                              d3.select(this).style("opacity","0.9")
                            if(d.order==129 || d.order==33 ){
                                    return "yellow";
                               }else if(d.order==65 || d.order==5 || d.order==17){
                                    return "red";
                               }
                           return "#00CC00";
                        }
                    }

                    return "#D0D0D0";
                    //return d.children ? "lightsteelblue" : "#fff";
                })

                .on("mouseover",function(d){
                    //d3.select(this).attr("class",'link2');

                            if(d.msg!=null){
                                tooltip.html(d.msg)
                                 .style("left", (d3.event.pageX-toottipWidth/2) + "px")
                                 .style("top", (d3.event.pageY + 20) + "px")
                                 .style({"opacity":"0.8","display":"block"});

                                 //console.log(d.msg);
                            }



                     })
                     .on("mousemove",function(d){
                         // 鼠标移动时,更改样式 left 和 top 来改变提示框的位置 
                         tooltip.style("left", (d3.event.pageX-toottipWidth/2) + "px")
                             .style("top", (d3.event.pageY + 20) + "px");

                     })
                     .on("mouseout",function(d){
                              //鼠标移出时,将透明度设定为0.0(完全透明)
                             tooltip.style({"opacity":"0.0","display":"none"});
                            // d3.select(this).attr("class",'link');
                     });

            // Transition nodes to their new position.
            var nodeUpdate = node.transition()
                .duration(duration)
                .attr("transform", function(d) {
                    return "translate(" + d.y + "," + d.x + ")";
                });


            // Fade the text in
            nodeUpdate.select("text")
                .style("fill-opacity", 1);

            // Transition exiting nodes to the parent's new position.
            var nodeExit = node.exit().transition()
                .duration(duration)
                .attr("transform", function(d) {
                    return "translate(" + source.y + "," + source.x + ")";
                })
                .remove();
/**
            nodeExit.select("circle")
                .attr("r", 0);

            nodeExit.select("text")
                .style("fill-opacity", 0);**/

            // Update the links…
            var link = svgGroup.selectAll("path.link")
                .data(links, function(d) {
                    return d.target.id;
                });

            // Enter any new links at the parent's previous position.
            link.enter().insert("path", "g")
                .attr("class", function(d){
                    if(d.target.order <= statusValue ){
                        if(statusValue.toString(2).indexOf(d.target.order.toString(2),0)==0)
                           return "link2";
                    }
                    return "link1";
                })
                .attr("d", function(d) {
                    var o = {
                        x: source.x0,
                        y: source.y0
                    };
                    return diagonal({
                        source: o,
                        target: o
                    });
                })


            // Transition links to their new position.
            link.transition()
                .duration(duration)
                .attr("d", diagonal);

            // Transition exiting nodes to the parent's new position.
            link.exit().transition()
                .duration(duration)
                .attr("d", function(d) {
                    var o = {
                        x: source.x,
                        y: source.y
                    };
                    return diagonal({
                        source: o,
                        target: o
                    });
                })
                .remove();

            // Stash the old positions for transition.
            nodes.forEach(function(d) {
                d.x0 = d.x;
                d.y0 = d.y;
            });
        }

        // Append a group which holds all nodes and which the zoom Listener can act upon.
        var svgGroup = baseSvg.append("g");

        // Define the root
        root = treeData;
        root.x0 = viewerHeight / 2;
        root.y0 = 0;

        // Layout the tree initially and center on the root node.
        update(root);
        centerNode(root);
        if(currentNode!=null){
            //定时器,颜色变化
          var opacity= currentNode.style.opacity;
          var dire=1;
          console.log(opacity);
          var timer = setInterval(function () {
                if(dire==1){
                    opacity -= .05;
                }else{
                    opacity +=.05;
                }

                if (opacity < 0.1 || opacity>1) {
                      dire= 1-dire;
                }
               d3.select(currentNode).style("opacity",opacity).attr("r", 10-opacity*4);
         }, 100);
        }




}

css:

.link1{
   fill: none;
  stroke:#D0D0D0;
  stroke-width: 1.5px;
  opacity:0.5;
}
.link2 {
    fill: none;
    stroke:#e38d13;
    stroke-width: 3px;
     opacity:0.5;
}






.node {
    cursor: pointer;
}

.overlay{
    background-color:#EEE;
    width:100%;
    height:100%;
}
.node circle {
    fill: green;
    stroke: steelblue;
    stroke-width: 1.5px;
    opacity:0.4;
}
.node text {
    font-size:10px;
    font-family:sans-serif;
}

.link {
    fill:none;
    stroke: #ccc;
    stroke-width: 2px;
}

.node>.nodeCircleLight{stroke-width: 5px;stroke:green;width: 15px;}
.templink {
    fill: none;
    stroke: red;
    stroke-width: 3px;
}
.ghostCircle.show{
    display:block;
}
.ghostCircle, .activeDrag .ghostCircle{
    display: none;
}
.test li{ list-style: none;}
.show-wrap{margin:10px;}
.showTree{float:left;width:100%;}
.full-con{height:500px;}
.full-con h2 {display: block;margin:0;padding:10px 0 0 25px;height:50px;border-radius:15px 15px 0 0;margin-top:-1px;}
.showArea{position:relative;float:right;width:30%;margin-left:-30%;min-height:500px;border:solid 1px #269abc;border-radius: 15px;}
.fullScreen{
    text-align:center;
    border-radius: 15px;
    overflow: hidden;
    height:100%;
}

/* Mozilla proposal (dash) */
.fullScreen:full-screen {
    width:100%;
    height:100%;
}
#tree-container2{
    width:100%;
    height:77%;
    poistion:absolute;
}
/* W3C proposal (no dash) */
.fullScreen:fullscreen {
    width:100%;
    height:100%;
}
/* currently working vendor prefixes */
.fullScreen:-webkit-full-screen, .fullScreen:-moz-full-screen {
    width:100%;
    height:100%;
}
:-webkit-full-screen{
    width:100%;
    height:100%;
}

#fullScreenBtn{border:none;height:30px;line-height:10px;}
.overRect{z-index: 99999;position: absolute;}
.nodeSpanText{float:left;font-family:sans-serif;font-size:12px;}
.table{margin-bottom:0;}
.table td,.table th{text-align:center;}
.nodeText{width:120px;height:60px;display:inline-block;}
.tableCode{margin-top:10px;margin-bottom:0;border:2px solid #ddd;}
.tableCode td{ border-top: none;}
.tableCode a{color: #000; cursor: pointer;}
.control-group{float:left;margin-left:25px;}
.control-group .control-label{float:left;padding-top:0;padding-right:10px;line-height:25px;}
.control-group .controls{float:left;margin-right:20px;line-height:25px;}
/* 带点文字链接列表-默认方点 */
.m-list2{line-height:1.5;margin:0;padding:0; margin-top: 10px;}
.m-list2 li{padding-left:10px;margin-top:5px; list-style: none; text-align: center;}
.m-list2 li:first-child{margin-top:0;}
.m-list2 li a{}
.m-list2 li a:hover{color:#269abc;}
.returnCode{display:inline-block;width:100px;height:30px;color: #000; background-color:#bbb;cursor: pointer; line-height: 30px;}
.returnCode input{display:inline-block;width:100px;height:30px;background:none;border:0;color: #000; cursor: pointer; line-height: 30px;}
.lj-check{display:inline-block;background-color: #d58512;width:100px;}
.codeValue{overflow: hidden; /*自动隐藏文字*/
    text-overflow: ellipsis;/*文字隐藏后添加省略号*/
    white-space: nowrap;/*强制不换行*/
    cursor: pointer;
    text-align:center;
}
.pathListWrap td{float:left;}
.tableCode {overflow-x:auto;}
.tableCode .nameGroupInt {margin-top:10px;width:100%;height:30px;line-height: 30px;background-color:gainsboro;border:0;}
.tableCode>tbody>tr>td, .tableCode>tbody>tr>th{display:inline-block;width:160px;}
.nameGroup{cursor: pointer;}
.tableCode a:not(.btn){text-decoration:none;text-align:center;}
.tableCode .returnCodeEdit{display:inline-block;height:30px; line-height: 30px;border:0;background-color: #d0e9c6;cursor: pointer;font-size:12px;text-align:center;}
.returnCodeEdit{width:40px;}
.tableCode a .nameGroup{color:green;display:block;text-align:center;}
.addTR td{background-color:#ddd;}
.nodeSpanTextCode{color:red;}
.codeGN input{display:inline-block;width:100px;background:none;border:0; cursor: pointer;height:30px; line-height: 30px;}
.trCodeGroup .modelCodeEdit{display:inline-block;height:30px; line-height: 30px;border:0;background-color: #d0e9c6;cursor: pointer;font-size:12px;text-align:center;}
.page-header{margin:0;padding:0;}
.breadcrumb{margin:0 0 5px 0;}
.main{padding-bottom:0;}

.tooltip{
    position: absolute;
    width:500px;
    word-wrap:break-word;
    min-height:100px;
    background:#d0e9c6;
    padding:20px;
    font-family: simsun;
    font-size: 14px;
    line-height:30px;
    color:#000;
    text-align:left;
    border:dotted 1px #ccc;
    border-radius: 15px;
}

.tooltip2{
    position: absolute;
    width:200px;
    word-wrap:break-word;
    min-height:50px;
    background:#444;
    padding:10px;
    font-family: 'Trebuchet MS', Helvetica, sans-serif;
    font-size: 11px;
    line-height:30px;
    color:white;
    text-align:center;
    border:dotted 1px #ccc;
    border-radius: 15px;
}

.ui-form-item-show .form-control{
    background-color:transparent;
     border:1px solid #ccc;
    cursor: text;
    color:#128F76;
    font-weight: bold
}
.ui-widget-content{
  border: 1px solid #dddddd;
  background: #fff;
  color: #333333;
  width: 700px;
}
.ui-menu .ui-menu-item {
  width: 700px;
  position: relative;
  margin: 0;
  padding: 3px 1em 3px .4em;
  cursor: pointer;
  min-height: 0;
  /* support: IE7; */
  /* support: IE10, see #8844; */
}
.titleshow{
   white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
}
#pointHoverTip{
  position:absolute; 
  width: 500px;
    word-wrap:break-word;
    min-height:100px;
    background:#d0e9c6;
    padding:20px;
    font-family: simsun;
    font-size: 14px;
    line-height:30px;
    color:#000;
    text-align:left;
    border:dotted 1px #ccc;
    border-radius: 15px;
    overflow-x:hidden;
  overflow-y:hidden;
    display:none;
}
@zhoupj
Copy link
Owner Author

zhoupj commented Jul 27, 2016

5eae22fc98382598fb391a28e20941e1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant