Browse Source

Added directions for hierarchical view as per #25

css_transitions
Alex de Mulder 10 years ago
parent
commit
c0c62bfd67
5 changed files with 141 additions and 42 deletions
  1. +43
    -18
      dist/vis.js
  2. +19
    -4
      docs/graph.html
  3. +36
    -2
      examples/graph/23_hierarchical_layout.html
  4. +2
    -9
      src/graph/Graph.js
  5. +41
    -9
      src/graph/graphMixins/HierarchicalLayoutMixin.js

+ 43
- 18
dist/vis.js View File

@ -12131,7 +12131,9 @@ var HierarchicalLayoutMixin = {
*/ */
_setupHierarchicalLayout : function() { _setupHierarchicalLayout : function() {
if (this.constants.hierarchicalLayout.enabled == true) { if (this.constants.hierarchicalLayout.enabled == true) {
if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "DU") {
this.constants.hierarchicalLayout.levelSeparation *= -1;
}
// get the size of the largest hubs and check if the user has defined a level for a node. // get the size of the largest hubs and check if the user has defined a level for a node.
var hubsize = 0; var hubsize = 0;
var node, nodeId; var node, nodeId;
@ -12195,10 +12197,21 @@ var HierarchicalLayoutMixin = {
for (nodeId in distribution[0].nodes) { for (nodeId in distribution[0].nodes) {
if (distribution[0].nodes.hasOwnProperty(nodeId)) { if (distribution[0].nodes.hasOwnProperty(nodeId)) {
node = distribution[0].nodes[nodeId]; node = distribution[0].nodes[nodeId];
if (node.xFixed) {
node.x = distribution[0].minPos;
distribution[0].minPos += distribution[0].nodeSpacing;
node.xFixed = false;
if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") {
if (node.xFixed) {
node.x = distribution[0].minPos;
node.xFixed = false;
distribution[0].minPos += distribution[0].nodeSpacing;
}
}
else {
if (node.yFixed) {
node.y = distribution[0].minPos;
node.yFixed = false;
distribution[0].minPos += distribution[0].nodeSpacing;
}
} }
this._placeBranchNodes(node.edges,node.id,distribution,node.level); this._placeBranchNodes(node.edges,node.id,distribution,node.level);
} }
@ -12226,7 +12239,12 @@ var HierarchicalLayoutMixin = {
node = this.nodes[nodeId]; node = this.nodes[nodeId];
node.xFixed = true; node.xFixed = true;
node.yFixed = true; node.yFixed = true;
node.y = this.constants.hierarchicalLayout.levelSeparation*node.level;
if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") {
node.y = this.constants.hierarchicalLayout.levelSeparation*node.level;
}
else {
node.x = this.constants.hierarchicalLayout.levelSeparation*node.level;
}
if (!distribution.hasOwnProperty(node.level)) { if (!distribution.hasOwnProperty(node.level)) {
distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0};
} }
@ -12329,9 +12347,23 @@ var HierarchicalLayoutMixin = {
} }
// if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here. // if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here.
if (childNode.xFixed && childNode.level > parentLevel) {
childNode.xFixed = false;
childNode.x = distribution[childNode.level].minPos;
var nodeMoved = false;
if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") {
if (childNode.xFixed && childNode.level > parentLevel) {
childNode.xFixed = false;
childNode.x = distribution[childNode.level].minPos;
nodeMoved = true;
}
}
else {
if (childNode.yFixed && childNode.level > parentLevel) {
childNode.yFixed = false;
childNode.y = distribution[childNode.level].minPos;
nodeMoved = true;
}
}
if (nodeMoved == true) {
distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing; distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing;
if (childNode.edges.length > 1) { if (childNode.edges.length > 1) {
this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level); this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level);
@ -15606,7 +15638,8 @@ function Graph (container, data, options) {
hierarchicalLayout: { hierarchicalLayout: {
enabled:false, enabled:false,
levelSeparation: 150, levelSeparation: 150,
nodeSpacing: 100
nodeSpacing: 100,
direction: "UD" // UD, DU, LR, RL
}, },
smoothCurves: true, smoothCurves: true,
maxVelocity: 10, maxVelocity: 10,
@ -15716,7 +15749,6 @@ function Graph (container, data, options) {
} }
} }
// if clustering is disabled, the simulation will have started in the setData function // if clustering is disabled, the simulation will have started in the setData function
if (this.constants.clustering.enabled) { if (this.constants.clustering.enabled) {
this.startWithClustering(); this.startWithClustering();
@ -16389,7 +16421,6 @@ Graph.prototype._onTap = function (event) {
Graph.prototype._onDoubleTap = function (event) { Graph.prototype._onDoubleTap = function (event) {
var pointer = this._getPointer(event.gesture.center); var pointer = this._getPointer(event.gesture.center);
this._handleDoubleTap(pointer); this._handleDoubleTap(pointer);
}; };
@ -17404,12 +17435,6 @@ Graph.prototype._initializeMixinLoaders = function () {
/** /**
* vis.js module exports * vis.js module exports
*/ */

+ 19
- 4
docs/graph.html View File

@ -1663,12 +1663,20 @@ var options: {
hierarchicalLayout: true hierarchicalLayout: true
} }
// advanced configuration for keyboard controls
// advanced configuration for hierarchical layout
var options: { var options: {
hierarchicalLayout: { hierarchicalLayout: {
enabled:false, enabled:false,
levelSeparation: 150, levelSeparation: 150,
nodeSpacing: 100
nodeSpacing: 100,
direction: "UD"
}
}
// partial configuration automatically sets enabled to true
var options: {
hierarchicalLayout: {
nodeSpacing: 100,
direction: "UD"
} }
} }
</pre> </pre>
@ -1692,13 +1700,20 @@ var options: {
<td>levelSeparation</td> <td>levelSeparation</td>
<td>Number</td> <td>Number</td>
<td>150</td> <td>150</td>
<td>This defines the space between levels (in the Y-direction).</td>
<td>This defines the space between levels (in the Y-direction, considering UP-DOWN direction).</td>
</tr> </tr>
<tr> <tr>
<td>nodeSpacing</td> <td>nodeSpacing</td>
<td>Number</td> <td>Number</td>
<td>100</td> <td>100</td>
<td>This defines the space between nodes in the same level (in the X-direction).</td>
<td>This defines the space between nodes in the same level (in the X-direction, considering UP-DOWN direction).</td>
</tr>
<tr>
<td>direction</td>
<td>String</td>
<td>UD</td>
<td>This defines the direction the graph is drawn in. The supported directions are: Up-Down (UD), Down-Up (DU), Left-Right (LR) and Right-Left (RL).
These need to be supplied by the acronyms in parentheses.</td>
</tr> </tr>
</table> </table>
<h2 id="Methods">Methods</h2> <h2 id="Methods">Methods</h2>

+ 36
- 2
examples/graph/23_hierarchical_layout.html View File

@ -21,6 +21,8 @@
var edges = null; var edges = null;
var graph = null; var graph = null;
function draw() { function draw() {
nodes = []; nodes = [];
edges = []; edges = [];
@ -75,12 +77,14 @@
nodes: nodes, nodes: nodes,
edges: edges edges: edges
}; };
var directionInput = document.getElementById("direction");
var options = { var options = {
edges: { edges: {
}, },
stabilize: false, stabilize: false,
hierarchicalLayout:true
hierarchicalLayout: {
direction: directionInput.value
}
}; };
graph = new vis.Graph(container, data, options); graph = new vis.Graph(container, data, options);
@ -89,6 +93,7 @@
document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes; document.getElementById('selection').innerHTML = 'Selection: ' + params.nodes;
}); });
} }
</script> </script>
</head> </head>
@ -104,6 +109,35 @@
<input id="nodeCount" type="text" value="25" style="width: 50px;"> <input id="nodeCount" type="text" value="25" style="width: 50px;">
<input type="submit" value="Go"> <input type="submit" value="Go">
</form> </form>
<input type="button" id="btn-UD" value="Up-Down">
<input type="button" id="btn-DU" value="Down-Up">
<input type="button" id="btn-LR" value="Left-Right">
<input type="button" id="btn-RL" value="Right-Left">
<input type="hidden" id='direction' value="UD">
<script language="javascript">
var directionInput = document.getElementById("direction");
var btnUD = document.getElementById("btn-UD");
btnUD.onclick = function() {
directionInput.value = "UD";
draw();
}
var btnDU = document.getElementById("btn-DU");
btnDU.onclick = function() {
directionInput.value = "DU";
draw();
};
var btnLR = document.getElementById("btn-LR");
btnLR.onclick = function() {
directionInput.value = "LR";
draw();
};
var btnRL = document.getElementById("btn-RL");
btnRL.onclick = function() {
directionInput.value = "RL";
draw();
};
</script>
<br> <br>
<div id="mygraph"></div> <div id="mygraph"></div>

+ 2
- 9
src/graph/Graph.js View File

@ -138,7 +138,8 @@ function Graph (container, data, options) {
hierarchicalLayout: { hierarchicalLayout: {
enabled:false, enabled:false,
levelSeparation: 150, levelSeparation: 150,
nodeSpacing: 100
nodeSpacing: 100,
direction: "UD" // UD, DU, LR, RL
}, },
smoothCurves: true, smoothCurves: true,
maxVelocity: 10, maxVelocity: 10,
@ -248,7 +249,6 @@ function Graph (container, data, options) {
} }
} }
// if clustering is disabled, the simulation will have started in the setData function // if clustering is disabled, the simulation will have started in the setData function
if (this.constants.clustering.enabled) { if (this.constants.clustering.enabled) {
this.startWithClustering(); this.startWithClustering();
@ -921,7 +921,6 @@ Graph.prototype._onTap = function (event) {
Graph.prototype._onDoubleTap = function (event) { Graph.prototype._onDoubleTap = function (event) {
var pointer = this._getPointer(event.gesture.center); var pointer = this._getPointer(event.gesture.center);
this._handleDoubleTap(pointer); this._handleDoubleTap(pointer);
}; };
@ -1935,9 +1934,3 @@ Graph.prototype._initializeMixinLoaders = function () {

+ 41
- 9
src/graph/graphMixins/HierarchicalLayoutMixin.js View File

@ -9,7 +9,9 @@ var HierarchicalLayoutMixin = {
*/ */
_setupHierarchicalLayout : function() { _setupHierarchicalLayout : function() {
if (this.constants.hierarchicalLayout.enabled == true) { if (this.constants.hierarchicalLayout.enabled == true) {
if (this.constants.hierarchicalLayout.direction == "RL" || this.constants.hierarchicalLayout.direction == "DU") {
this.constants.hierarchicalLayout.levelSeparation *= -1;
}
// get the size of the largest hubs and check if the user has defined a level for a node. // get the size of the largest hubs and check if the user has defined a level for a node.
var hubsize = 0; var hubsize = 0;
var node, nodeId; var node, nodeId;
@ -73,10 +75,21 @@ var HierarchicalLayoutMixin = {
for (nodeId in distribution[0].nodes) { for (nodeId in distribution[0].nodes) {
if (distribution[0].nodes.hasOwnProperty(nodeId)) { if (distribution[0].nodes.hasOwnProperty(nodeId)) {
node = distribution[0].nodes[nodeId]; node = distribution[0].nodes[nodeId];
if (node.xFixed) {
node.x = distribution[0].minPos;
distribution[0].minPos += distribution[0].nodeSpacing;
node.xFixed = false;
if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") {
if (node.xFixed) {
node.x = distribution[0].minPos;
node.xFixed = false;
distribution[0].minPos += distribution[0].nodeSpacing;
}
}
else {
if (node.yFixed) {
node.y = distribution[0].minPos;
node.yFixed = false;
distribution[0].minPos += distribution[0].nodeSpacing;
}
} }
this._placeBranchNodes(node.edges,node.id,distribution,node.level); this._placeBranchNodes(node.edges,node.id,distribution,node.level);
} }
@ -104,7 +117,12 @@ var HierarchicalLayoutMixin = {
node = this.nodes[nodeId]; node = this.nodes[nodeId];
node.xFixed = true; node.xFixed = true;
node.yFixed = true; node.yFixed = true;
node.y = this.constants.hierarchicalLayout.levelSeparation*node.level;
if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") {
node.y = this.constants.hierarchicalLayout.levelSeparation*node.level;
}
else {
node.x = this.constants.hierarchicalLayout.levelSeparation*node.level;
}
if (!distribution.hasOwnProperty(node.level)) { if (!distribution.hasOwnProperty(node.level)) {
distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0};
} }
@ -207,9 +225,23 @@ var HierarchicalLayoutMixin = {
} }
// if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here. // if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here.
if (childNode.xFixed && childNode.level > parentLevel) {
childNode.xFixed = false;
childNode.x = distribution[childNode.level].minPos;
var nodeMoved = false;
if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") {
if (childNode.xFixed && childNode.level > parentLevel) {
childNode.xFixed = false;
childNode.x = distribution[childNode.level].minPos;
nodeMoved = true;
}
}
else {
if (childNode.yFixed && childNode.level > parentLevel) {
childNode.yFixed = false;
childNode.y = distribution[childNode.level].minPos;
nodeMoved = true;
}
}
if (nodeMoved == true) {
distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing; distribution[childNode.level].minPos += distribution[childNode.level].nodeSpacing;
if (childNode.edges.length > 1) { if (childNode.edges.length > 1) {
this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level); this._placeBranchNodes(childNode.edges,childNode.id,distribution,childNode.level);

Loading…
Cancel
Save