绘制人物关系图




<!DOCTYPE html>
<html>
<head>
<script type= "text/javascript" src= "http://mbostock.github.com/d3/d3.v2.js?2.9.1" ></script>
<style type= "text/css" >
.link { stroke: green; stroke-linejoin:bevel;}
 
.link_error{
     stroke:red;
     stroke-linejoin:bevel;
}
 
.nodetext {
 
     font: 12px sans-serif;
     -webkit-user-select:none;
     -moze-user-select:none;
     stroke-linejoin:bevel;
     
}
 
#container{
     width:800px;
     height:600px;
     border:1px solid gray;
     border-radius:5px;
     position:relative;
     margin:20px;
}
</style>
</head>
<body>
     <div id= 'container' ></div>
<script type= "text/javascript" >
 
function Topology(ele){
     typeof(ele)== 'string' && (ele=document.getElementById(ele));
     var w=ele.clientWidth,
         h=ele.clientHeight,
         self= this ;
     this .force = d3.layout.force().gravity(. 05 ).distance( 200 ).charge(- 800 ).size([w, h]);
     this .nodes= this .force.nodes();
     this .links= this .force.links();
     this .clickFn=function(){};
     this .vis = d3.select(ele).append( "svg:svg" )
                  .attr( "width" , w).attr( "height" , h).attr( "pointer-events" , "all" );
 
     this .force.on( "tick" , function(x) {
       self.vis.selectAll( "g.node" )
           .attr( "transform" , function(d) { return "translate(" + d.x + "," + d.y + ")" ; });
 
       self.vis.selectAll( "line.link" )
           .attr( "x1" , function(d) { return d.source.x; })
           .attr( "y1" , function(d) { return d.source.y; })
           .attr( "x2" , function(d) { return d.target.x; })
           .attr( "y2" , function(d) { return d.target.y; });
     });
}
 
 
Topology.prototype.doZoom=function(){
     d3.select( this ).select( 'g' ).attr( "transform" , "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")" );
 
}
 
 
//增加节点
Topology.prototype.addNode=function(node){
     this .nodes.push(node);
}
 
Topology.prototype.addNodes=function(nodes){
     if (Object.prototype.toString.call(nodes)== '[object Array]' ){
         var self= this ;
         nodes.forEach(function(node){
             self.addNode(node);
         });
 
     }
}
 
//增加连线
Topology.prototype.addLink=function(source,target){
     this .links.push({source: this .findNode(source),target: this .findNode(target)});
}
 
//增加多个连线
Topology.prototype.addLinks=function(links){
     if (Object.prototype.toString.call(links)== '[object Array]' ){
         var self= this ;
         links.forEach(function(link){
             self.addLink(link[ 'source' ],link[ 'target' ]);
         });
     }
}
 
 
//删除节点
Topology.prototype.removeNode=function(id){
     var i= 0 ,
         n= this .findNode(id),
         links= this .links;
     while ( i < links.length){
         links[i][ 'source' ]==n || links[i][ 'target' ] ==n ? links.splice(i, 1 ) : ++i;
     }
     this .nodes.splice( this .findNodeIndex(id), 1 );
}
 
//删除节点下的子节点,同时清除link信息
Topology.prototype.removeChildNodes=function(id){
     var node= this .findNode(id),
         nodes= this .nodes;
         links= this .links,
         self= this ;
 
     var linksToDelete=[],
         childNodes=[];
     
     links.forEach(function(link,index){
         link[ 'source' ]==node
             && linksToDelete.push(index)
             && childNodes.push(link[ 'target' ]);
     });
 
     linksToDelete.reverse().forEach(function(index){
         links.splice(index, 1 );
     });
 
     var remove=function(node){
         var length=links.length;
         for (var i=length- 1 ;i>= 0 ;i--){
             if (links[i][ 'source' ] == node ){
                var target=links[i][ 'target' ];
                links.splice(i, 1 );
                nodes.splice(self.findNodeIndex(node.id), 1 );
                remove(target);
                
             }
         }
     }
 
     childNodes.forEach(function(node){
         remove(node);
     });
 
     //清除没有连线的节点
     for (var i=nodes.length- 1 ;i>= 0 ;i--){
         var haveFoundNode= false ;
         for (var j= 0 ,l=links.length;j<l;j++){
             ( links[j][ 'source' ]==nodes[i] || links[j][ 'target' ]==nodes[i] ) && (haveFoundNode= true )
         }
         !haveFoundNode && nodes.splice(i, 1 );
     }
}
 
 
 
//查找节点
Topology.prototype.findNode=function(id){
     var nodes= this .nodes;
     for (var i in nodes){
         if (nodes[i][ 'id' ]==id ) return nodes[i];
     }
     return null ;
}
 
 
//查找节点所在索引号
Topology.prototype.findNodeIndex=function(id){
     var nodes= this .nodes;
     for (var i in nodes){
         if (nodes[i][ 'id' ]==id ) return i;
     }
     return - 1 ;
}
 
//节点点击事件
Topology.prototype.setNodeClickFn=function(callback){
     this .clickFn=callback;
}
 
//更新拓扑图状态信息
Topology.prototype.update=function(){
   var link = this .vis.selectAll( "line.link" )
       .data( this .links, function(d) { return d.source.id + "-" + d.target.id; })
       .attr( "class" , function(d){
             return d[ 'source' ][ 'status' ] && d[ 'target' ][ 'status' ] ? 'link' : 'link link_error' ;
       });
 
   link.enter().insert( "svg:line" , "g.node" )
       .attr( "class" , function(d){
          return d[ 'source' ][ 'status' ] && d[ 'target' ][ 'status' ] ? 'link' : 'link link_error' ;
       });
 
   link.exit().remove();
 
   var node = this .vis.selectAll( "g.node" )
       .data( this .nodes, function(d) { return d.id;});
 
   var nodeEnter = node.enter().append( "svg:g" )
       .attr( "class" , "node" )
       .call( this .force.drag);
 
   //增加图片,可以根据需要来修改
   var self= this ;
   nodeEnter.append( "svg:image" )
       .attr( "class" , "circle" )
       .attr( "xlink:href" , function(d){
          //根据类型来使用图片
          return d.expand ? "http://ww2.sinaimg.cn/large/412e82dbjw1dsbny7igx2j.jpg" : "http://ww4.sinaimg.cn/large/412e82dbjw1dsbnxezrrpj.jpg" ;
       })
       .attr( "x" , "-32px" )
       .attr( "y" , "-32px" )
       .attr( "width" , "64px" )
       .attr( "height" , "64px" )
       .on( 'click' ,function(d){ d.expand && self.clickFn(d);})
 
   nodeEnter.append( "svg:text" )
       .attr( "class" , "nodetext" )
       .attr( "dx" , 15 )
       .attr( "dy" , - 35 )
       .text(function(d) { return d.id });
 
   
   node.exit().remove();
 
   this .force.start();
}
 
 
 
 
var topology= new Topology( 'container' );
 
var nodes=[
     {id: '10.4.42.1' ,type: 'router' ,status: 1 },
     {id: '10.4.43.1' ,type: 'switch' ,status: 1 ,expand: true },
     {id: '10.4.44.1' ,type: 'switch' ,status: 1 },
     {id: '10.4.45.1' ,type: 'switch' ,status: 0 }
 
];
 
var childNodes=[
     {id: '10.4.43.2' ,type: 'switch' ,status: 1 },
     {id: '10.4.43.3' ,type: 'switch' ,status: 1 }
 
];
 
var links=[
     {source: '10.4.42.1' ,target: '10.4.43.1' },
     {source: '10.4.42.1' ,target: '10.4.44.1' },
     {source: '10.4.42.1' ,target: '10.4.45.1' }
];
 
var childLinks=[
     {source: '10.4.43.1' ,target: '10.4.43.2' },
     {source: '10.4.43.1' ,target: '10.4.43.3' },
     {source: '10.4.43.2' ,target: '10.4.43.3' }
]
 
 
topology.addNodes(nodes);
topology.addLinks(links);
//可展开节点的点击事件
topology.setNodeClickFn(function(node){
     if (!node[ '_expanded' ]){
         expandNode(node.id);
         node[ '_expanded' ]= true ;
     } else {
         collapseNode(node.id);
         node[ '_expanded' ]= false ;
     }
});
topology.update();
 
 
function expandNode(id){
     topology.addNodes(childNodes);
     topology.addLinks(childLinks);
     topology.update();
}
 
function collapseNode(id){
     topology.removeChildNodes(id);
     topology.update();
}
 
</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值