2015-07-01 10 views
5

Mam wykres sieciowy w vis.js z wieloma węzłami. Wybierając określoną grupę, chciałbym przesuwać i powiększać wykres tak, aby wszystkie węzły tej grupy pasowały do ​​ekranu.vis.js - dopasuj zestaw węzłów na ekranie

Przechodzę przez każdy węzeł na wykresie i obliczam pole ograniczające dla wszystkich węzłów, które mnie interesują, a następnie używam metody moveTo do przesuwania i skalowania wykresu do środka tego obwiedni. Pseudokod:

var allNodes = data.nodes.get({ 
    returnType: "Object" 
}); 
var bounds; 
for (n in allNodes) { 
    if (matchesCondition(allNodes[n])) { 
     bounds = extendBounds(bounds, graph.getBoundingBox(allNodes[n]));     
    } 
} 
var newViewport = { 
    position: { 
     x: (bounds.x1+bounds.x2)/2; 
     y: (bounds.y1+bounds.y2)/2; 
    }, 
    // What is the visible width, where do I get it from? 
    scale: Math.min(???/(bounds.x2-bounds.x1), ???/(bounds.y2-bounds.y1)) 
} 
graph.moveTo(newViewport); 

Pytanie: jak obliczyć skalę, tj. Co mam zastąpić ??? z powyższym pseudokodem?

Odpowiedz

7

Przykładowe dane z Vis.js groups example.

Aby dopasować rzutnię, można po prostu użyć natywnej metody .fit(). Ponieważ the documentation nie udostępnia odnośników hashtaggable, oto opis interfejsu API:

Powiększa wszystkie węzły pasujące do obszaru roboczego. Można dostarczyć opcje do dostosować to:

{ 
    nodes:[Array of nodeIds], 
    animation: { //can be a boolean too 
    duration: Number 
    easingFunction: String 
    } 
} 

Węzły mogą być wykorzystane, aby przybliżyć się zmieścić tylko konkretne węzły w widoku.

Mając to na uwadze, wszystko, co musimy zrobić, to uzyskać wszystkie węzły w danej grupie. Co zaskakujące, interfejs API user-land nie oferuje tej metody (?), Więc niezbędna jest niewielka metoda filtrowania.

//TODO: Is there no user-land API for this? 
 
var getGroup = function getGroup(nodeId) { 
 
    var nodesHandler = network.nodesHandler; 
 
    var innerNodes = nodesHandler.body.nodes; 
 
    //Lazily assume ids match indices 
 
    var node = innerNodes[nodeId]; 
 
    return node.options.group; 
 
}; 
 

 
var getGroupNodes = function getGroupNodes(group) { 
 
    // http://elijahmanor.com/reducing-filter-and-map-down-to-reduce/ 
 
    var filtered = nodes.reduce(function(output, node) { 
 
    if (node.group === group) { 
 
     output.push(node.id); 
 
    } 
 
    return output; 
 
    }, []); 
 
    return filtered; 
 
}; 
 

 
//START Vis.js group example 
 

 
var color = 'gray'; 
 
var len = undefined; 
 

 
var nodes = [{ 
 
    id: 0, 
 
    label: "0", 
 
    group: 0 
 
}, { 
 
    id: 1, 
 
    label: "1", 
 
    group: 0 
 
}, { 
 
    id: 2, 
 
    label: "2", 
 
    group: 0 
 
}, { 
 
    id: 3, 
 
    label: "3", 
 
    group: 1 
 
}, { 
 
    id: 4, 
 
    label: "4", 
 
    group: 1 
 
}, { 
 
    id: 5, 
 
    label: "5", 
 
    group: 1 
 
}, { 
 
    id: 6, 
 
    label: "6", 
 
    group: 2 
 
}, { 
 
    id: 7, 
 
    label: "7", 
 
    group: 2 
 
}, { 
 
    id: 8, 
 
    label: "8", 
 
    group: 2 
 
}, { 
 
    id: 9, 
 
    label: "9", 
 
    group: 3 
 
}, { 
 
    id: 10, 
 
    label: "10", 
 
    group: 3 
 
}, { 
 
    id: 11, 
 
    label: "11", 
 
    group: 3 
 
}, { 
 
    id: 12, 
 
    label: "12", 
 
    group: 4 
 
}, { 
 
    id: 13, 
 
    label: "13", 
 
    group: 4 
 
}, { 
 
    id: 14, 
 
    label: "14", 
 
    group: 4 
 
}, { 
 
    id: 15, 
 
    label: "15", 
 
    group: 5 
 
}, { 
 
    id: 16, 
 
    label: "16", 
 
    group: 5 
 
}, { 
 
    id: 17, 
 
    label: "17", 
 
    group: 5 
 
}, { 
 
    id: 18, 
 
    label: "18", 
 
    group: 6 
 
}, { 
 
    id: 19, 
 
    label: "19", 
 
    group: 6 
 
}, { 
 
    id: 20, 
 
    label: "20", 
 
    group: 6 
 
}, { 
 
    id: 21, 
 
    label: "21", 
 
    group: 7 
 
}, { 
 
    id: 22, 
 
    label: "22", 
 
    group: 7 
 
}, { 
 
    id: 23, 
 
    label: "23", 
 
    group: 7 
 
}, { 
 
    id: 24, 
 
    label: "24", 
 
    group: 8 
 
}, { 
 
    id: 25, 
 
    label: "25", 
 
    group: 8 
 
}, { 
 
    id: 26, 
 
    label: "26", 
 
    group: 8 
 
}, { 
 
    id: 27, 
 
    label: "27", 
 
    group: 9 
 
}, { 
 
    id: 28, 
 
    label: "28", 
 
    group: 9 
 
}, { 
 
    id: 29, 
 
    label: "29", 
 
    group: 9 
 
}]; 
 
var edges = [{ 
 
    from: 1, 
 
    to: 0 
 
}, { 
 
    from: 2, 
 
    to: 0 
 
}, { 
 
    from: 4, 
 
    to: 3 
 
}, { 
 
    from: 5, 
 
    to: 4 
 
}, { 
 
    from: 4, 
 
    to: 0 
 
}, { 
 
    from: 7, 
 
    to: 6 
 
}, { 
 
    from: 8, 
 
    to: 7 
 
}, { 
 
    from: 7, 
 
    to: 0 
 
}, { 
 
    from: 10, 
 
    to: 9 
 
}, { 
 
    from: 11, 
 
    to: 10 
 
}, { 
 
    from: 10, 
 
    to: 4 
 
}, { 
 
    from: 13, 
 
    to: 12 
 
}, { 
 
    from: 14, 
 
    to: 13 
 
}, { 
 
    from: 13, 
 
    to: 0 
 
}, { 
 
    from: 16, 
 
    to: 15 
 
}, { 
 
    from: 17, 
 
    to: 15 
 
}, { 
 
    from: 15, 
 
    to: 10 
 
}, { 
 
    from: 19, 
 
    to: 18 
 
}, { 
 
    from: 20, 
 
    to: 19 
 
}, { 
 
    from: 19, 
 
    to: 4 
 
}, { 
 
    from: 22, 
 
    to: 21 
 
}, { 
 
    from: 23, 
 
    to: 22 
 
}, { 
 
    from: 22, 
 
    to: 13 
 
}, { 
 
    from: 25, 
 
    to: 24 
 
}, { 
 
    from: 26, 
 
    to: 25 
 
}, { 
 
    from: 25, 
 
    to: 7 
 
}, { 
 
    from: 28, 
 
    to: 27 
 
}, { 
 
    from: 29, 
 
    to: 28 
 
}, { 
 
    from: 28, 
 
    to: 0 
 
}]; 
 

 
// create a network 
 
var container = document.getElementById('mynetwork'); 
 
var data = { 
 
    nodes: nodes, 
 
    edges: edges 
 
}; 
 
var options = { 
 
    nodes: { 
 
    shape: 'dot', 
 
    size: 30, 
 
    font: { 
 
     size: 32, 
 
     color: '#ffffff' 
 
    }, 
 
    borderWidth: 2 
 
    }, 
 
    edges: { 
 
    width: 2 
 
    } 
 
}; 
 
network = new vis.Network(container, data, options); 
 

 
//END Vis.js group example 
 

 
network.on("click", function(e) { 
 
    //Zoom only on single node clicks, zoom out otherwise 
 
    if (e.nodes.length !== 1) { 
 
    network.fit(); 
 
    return; 
 
    } 
 
    var nodeId = e.nodes[0]; 
 
    //Find out what group the node belongs to 
 
    var group = getGroup(nodeId); 
 
    //TODO: How do you want to handle ungrouped nodes? 
 
    if (group === undefined) return; 
 
    var groupNodes = getGroupNodes(group); 
 
    network.fit({ 
 
    nodes: groupNodes 
 
    }); 
 
});
html, 
 
body, 
 
#mynetwork { 
 
    width: 100%; 
 
    height: 100%; 
 
    margin: 0; 
 
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/vis/4.3.0/vis.min.js"></script> 
 
<div id="mynetwork"></div>

+0

Dzięki, powinien bardziej uważnie przeczytać dokumentację 'fit' metody ;-) –