后台返回的数据为WEBSOCKET实时推送 ,每推送一条数据来,自动生成一个分支和数据块,一个子可能会对应多个父。
每个绿色方块点击 出现对应的灰色方块
效果图如下:
html如下
<!doctype html>
<head>
<meta charset="utf-8">
<title>域名关系图</title>
<link rel="stylesheet" href="{{ STATIC_URL }}css/index.css">
</head>
<body>
<div class="content">
<svg id="svgCanvas"></svg>
</div>
<ul id="myMenu">
<li>http://192.68.102.11:/test/fileupload</li>
</ul>
</body>
<script type="text/javascript" src="{{ STATIC_URL }}js/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/d3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/dagre-d3.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/diag.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/index.js"></script>
</html>
css 如下
*{
font-family: 'Microsoft YaHei';
list-style: none;
padding: 0;
margin: 0;
}
html,body{
background-color: #f1f4f5;
overflow: hidden;
width: 100%;
height: 100%;
}
.content{
width: 100%;
height: 100%;
}
.content svg{
width: 100%;
}
.content svg >g{
width: 100%;
height: 100%;
}
/*漏洞信息*/
.looplist{
position: absolute;
right: 0;
top: 0;
width: 250px;
background-color: #fff;
height: 100%;
padding-left: 10px;
padding-right: 10px;
box-sizing: border-box;
border-left: 1px solid #d8e1e4;
}
.looplist >div{
position: relative;
height: 100%;
}
.looplist >div label{
position: absolute;
width: 20px;
height: 32px;
top: 50%;
margin-top: -16px;
left: -32px;
background-color: #fff;
border:1px solid #d8e1e4;
color: #a1b0b5;
text-align: center;
line-height: 32px;
cursor: pointer;
}
.looplist >div strong{
display: inline-block;
width: 100%;
font-size: 14px;
color: #687386;
padding-top: 10px;
padding-bottom: 10px;
}
.looplist >div li{
color: #687386;
font-size: 12px;
height: 40px;
line-height: 40px;
border-bottom: 1px solid #d8e1e4;
display:block;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
/* This sets the color for "TK" nodes to a light blue green. */
g.type-suss>rect {
fill: #ddefd3;
}
.node text {
font-weight: bold;
font-family: "Microsoft YaHei" ;
font-size: 12px;
pointer-events: none;
text-anchor: middle;
fill: white;
}
/*.label g text tspan:last-child {
font-size: 10px;
margin-top: 5px;
dy: 1.5em;
}*/
.label g {
transform: translate(0, -13px);
}
.node rect {
fill: white;
stroke-width: 0px;
color: white;
}
.edgePath path {
stroke: #ccc;
stroke-width: 1px;
}
g.type-suss >rect{
fill:#f68440
}
g.type-security>rect{
fill:#3fc96e;
}
g.type-init>rect {
stroke: #dee6e8;
stroke-width: 1px;
}
.type-init text tspan:nth-child(1) {
display: inline-block;
fill:#4487f4;
font-weight: bold;
text-align: left;
}
.type-init text tspan {
fill:#687386;
font-size: 12px;
font-weight: 100;
}
g.type-server>rect{
stroke: #dee6e8;
stroke-width: 1px;
}
.type-server text{
fill:#687386;
font-size: 14px;
}
g.type-port>rect{
fill:#dff0e7;
stroke: #3fc96e;
stroke-width: 1px;
}
.type-port text{
fill:#3fc96e;
font-size: 14px;
}
g.type-domain>rect{
fill: rgba(0,0,0,0);
}
.type-domain text{
fill:#4487f4;
font-size: 24px;
}
#myMenu{
position: absolute;
display: none;
min-width: 120px;
max-width:550px;
min-height: 50px;
max-height: 100px;
background: #fff;
border:1px solid #d8e1e4;
padding: 5px;
border-radius: 14px;
background: #a5e0ee;
border: 1px solid rgb(153, 153, 153);
}
#myMenu li{
width: 100%;
}
.systemlist{
position: absolute;
left: 20px;
top: 20px;
width: 220px;
height: 138px;
background-color: #fff;
border:1px solid #d8e1e4;
border-radius: 4px;
padding: 20px;
padding-bottom: 0;
box-sizing: border-box;
font-size: 12px;
color: #687386;
}
.systemlist ul{
margin:0;
}
.systemlist ul li{
width: 100%;
margin-bottom: 10px;
}
.systemlist ul li label{
display: inline-block;
font-weight: bold;
}
.systemlist ul li span{
}
js如下
$(function(){
state = [];
edg = [];
var websocket = null;
if ('WebSocket' in window) { //判断当前浏览器是否支持WebSocket
websocket = new WebSocket("ws://" + window.location.host + "/testWs");
}else {
alert('当前浏览器 不支持WebSocket');
}
websocket.onerror = function () { //连接发生错误的回调方法
console.log('发生异常');
};
websocket.onopen = function () { //连接成功建立的回调方法
console.log('连接成功');
}
websocket.onmessage = function (event) { //接收到消息的回调方法,此处添加处理接收消息方法,当前是将接收到的信息显示在网页上
try{
node_message = JSON.parse(event.data);
setTimeout(paint_node(node_message), 1000);
console.log(node_message)
}catch (e){
console.log(e);
}
}
websocket.onclose = function () { //连接关闭的回调方法
console.log('连接关闭');
}
window.onbeforeunload = function () { //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
closeWebSocket();
}
// 绘制的关键
function paint_node(node_message) { //将消息显示在网页上,如果不需要显示在网页上,则不调用该方法
if (node_message.node_indentity == 1){
var statePoint = 1;
state.push({id: node_message.node_indentity, label: node_message.node_title, class: 'type-domain'});
diagGraph.init(statePoint, state, edg); //创建关系图
}else{
try{
fatherNode = eval(node_message.fathernode);
// console.log("!!!"+node_message.node_content);
try{
$(fatherNode).each(function(index){ //有多个父节点的要遍历 自动生成一子对应多父
var nodeid=this;
edg.push({start: parseInt(nodeid), end: node_message.node_indentity, option: {}});
state.push({id: node_message.node_indentity, label: node_message.node_title, class: 'type-port', "value": node_message.node_content});
diagGraph.renderG()
})
}catch (e){
console.log(e);
}
}catch(e){
console.log();
}
}
}
var totalw = $('.content').width();
var totalh = $('.content').height();
$('#svgCanvas').attr({
width:totalw,
height:totalh
});
var myMenu = document.getElementById("myMenu");
$('#svgCanvas').on('click',function(e){
e.preventDefault();
if (e.target.tagName === 'rect') {
var id = e.target.parentNode.id;
diagGraph.changePoint(id);
var value="";
// console.log(state)
$(state).each(function(){
if(this.id==id){
value=this.value;
return false;
}
})
$('#myMenu').html("<li>"+value+"</li>");
$('#myMenu').css({left:event.clientX, top: event.clientY}).show();
} else {
$('#myMenu').hide();
}
})
});