Browse Source

fixed bugs in hierarchical layout. Fixed bugs in configuration, added wrapper to configuration divs,, made label optional for nodes, if no label, id will be shown. Support for value arrays in deepextend.

flowchartTest
Alex de Mulder 9 years ago
parent
commit
2256516cb6
9 changed files with 690 additions and 511 deletions
  1. +7
    -0
      dist/vis.css
  2. +550
    -493
      dist/vis.js
  3. +1
    -1
      dist/vis.min.css
  4. +95
    -0
      examples/network/layout.html
  5. +7
    -0
      lib/network/css/network-configuration.css
  6. +13
    -4
      lib/network/modules/ConfigurationSystem.js
  7. +10
    -7
      lib/network/modules/LayoutEngine.js
  8. +3
    -0
      lib/network/modules/components/Node.js
  9. +4
    -6
      lib/util.js

+ 7
- 0
dist/vis.css View File

@ -827,6 +827,12 @@ div.vis-network-configuration {
font-size:12px;
}
div.vis-network-configuration-wrapper {
display:block;
width:700px;
}
div.vis-network-configuration.vis-option-container{
display:block;
width:495px;
@ -862,6 +868,7 @@ div.vis-network-configuration.button.hover{
div.vis-network-configuration.item{
display:block;
float:left;
width:495px;
height:25px;
vertical-align: middle;

+ 550
- 493
dist/vis.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/vis.min.css
File diff suppressed because it is too large
View File


+ 95
- 0
examples/network/layout.html View File

@ -0,0 +1,95 @@
<!doctype html>
<html>
<head>
<title>Network | Basic usage</title>
<script type="text/javascript" src="../../dist/vis.js"></script>
<link href="../../dist/vis.css" rel="stylesheet" type="text/css"/>
<style type="text/css">
#mynetwork {
width: 1600px;
height:800px;
border: 1px solid lightgray;
}
</style>
<body>
<div id="mynetwork"></div>
<script type="text/javascript">
// create an array with nodes
var nodes = [
{id: 'network', shape:'database'},
{id: 'body', shape:'database'},
{id: 'nodes'},
{id: 'canvas'},
{id: 'edges'},
{id: 'nodesHandler'},
{id: 'edgesHandler'},
{id: 'selectionHandler'},
{id: 'interactionHandler'},
{id: 'view'},
{id: 'renderer'},
{id: 'physics'},
{id: 'layoutEngine'},
{id: 'clustering'},
{id: 'manipulation'},
{id: 'events'},
];
// create an array with edges
var edges = [
{from: 'network', to: 'body'},
{from: 'body', to: 'nodesHandler'},
{from: 'body', to: 'edgesHandler'},
{from: 'body', to: 'selectionHandler'},
{from: 'body', to: 'interactionHandler'},
{from: 'body', to: 'view'},
{from: 'body', to: 'renderer'},
{from: 'body', to: 'physics'},
{from: 'body', to: 'canvas'},
{from: 'body', to: 'layoutEngine'},
{from: 'body', to: 'clustering'},
{from: 'body', to: 'manipulation'},
{from: 'nodes', to: 'body'},
{from: 'nodes', to: 'nodesHandler'},
{from: 'edges', to: 'body'},
{from: 'edges', to: 'edgesHandler'},
{from: 'layoutEngine', to: 'nodesHandler'},
{from: 'canvas', to: 'manipulation'},
{from: 'canvas', to: 'renderer'},
{from: 'canvas', to: 'view'},
{from: 'canvas', to: 'selectionHandler'},
{from: 'canvas', to: 'interactionHandler'},
{from: 'selectionHandler', to: 'interactionHandler'},
{from: 'selectionHandler', to: 'manipulation'},
];
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
edges: {arrows: 'to', smooth:true},
layout:{hierarchical:{direction:'UD',levelSeparation: "260"}},
configure:'physics',
// "physics": {
// "hierarchicalRepulsion": {
// "centralGravity": 0,
// "nodeDistance": "220"
// },
// "solver": "hierarchicalRepulsion"
// }
// physics:{stabilization:true}
}
var network = new vis.Network(container, data, options);
// network.setOptions({nodes:{color:'red'}})
</script>
</body>
</html>

+ 7
- 0
lib/network/css/network-configuration.css View File

@ -5,6 +5,12 @@ div.vis-network-configuration {
font-size:12px;
}
div.vis-network-configuration-wrapper {
display:block;
width:700px;
}
div.vis-network-configuration.vis-option-container{
display:block;
width:495px;
@ -40,6 +46,7 @@ div.vis-network-configuration.button.hover{
div.vis-network-configuration.item{
display:block;
float:left;
width:495px;
height:25px;
vertical-align: middle;

+ 13
- 4
lib/network/modules/ConfigurationSystem.js View File

@ -165,7 +165,7 @@ class ConfigurationSystem {
},
physics: {
barnesHut: {
theta: [0.5, 0.1, 1, 0.05],
//theta: [0.5, 0.1, 1, 0.05],
gravitationalConstant: [-2000, -30000, 0, 50],
centralGravity: [0.3, 0, 10, 0.05],
springLength: [95, 0, 500, 5],
@ -216,6 +216,7 @@ class ConfigurationSystem {
this.domElements = [];
this.colorPicker = new ColorPicker(this.network.canvas.pixelRatio);
this.wrapper;
}
@ -321,8 +322,11 @@ class ConfigurationSystem {
* @private
*/
_push() {
this.wrapper = document.createElement('div');
this.wrapper.className = 'vis-network-configuration-wrapper';
this.container.appendChild(this.wrapper);
for (var i = 0; i < this.domElements.length; i++) {
this.container.appendChild(this.domElements[i]);
this.wrapper.appendChild(this.domElements[i]);
}
}
@ -332,7 +336,12 @@ class ConfigurationSystem {
*/
_clean() {
for (var i = 0; i < this.domElements.length; i++) {
this.container.removeChild(this.domElements[i]);
this.wrapper.removeChild(this.domElements[i]);
}
if (this.wrapper !== undefined) {
this.container.removeChild(this.wrapper);
this.wrapper = undefined;
}
this.domElements = [];
}
@ -380,7 +389,7 @@ class ConfigurationSystem {
* @param domElements
* @private
*/
_makeItem(path,...domElements) {
_makeItem(path, ...domElements) {
let item = document.createElement('div');
item.className = 'vis-network-configuration item s' + path.length;
domElements.forEach((element) => {

+ 10
- 7
lib/network/modules/LayoutEngine.js View File

@ -159,6 +159,7 @@ class LayoutEngine {
this._determineLevelsDirected();
}
}
// check the distribution of the nodes per level.
let distribution = this._getDistribution();
@ -177,7 +178,6 @@ class LayoutEngine {
_placeNodesByHierarchy(distribution) {
let nodeId, node;
this.positionedNodes = {};
// start placing all the level 0 nodes first. Then recursively position their branches.
for (let level in distribution) {
if (distribution.hasOwnProperty(level)) {
@ -185,6 +185,7 @@ class LayoutEngine {
if (distribution[level].nodes.hasOwnProperty(nodeId)) {
node = distribution[level].nodes[nodeId];
if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") {
if (node.x === undefined) {node.x = distribution[level].distance;}
distribution[level].distance = node.x + this.nodeSpacing;
@ -218,19 +219,20 @@ class LayoutEngine {
for (nodeId in this.body.nodes) {
if (this.body.nodes.hasOwnProperty(nodeId)) {
node = this.body.nodes[nodeId];
let level = this.hierarchicalLevels[nodeId] === undefined ? 0 : this.hierarchicalLevels[nodeId];
if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") {
node.y = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId];
node.y = this.options.hierarchical.levelSeparation * level;
node.options.fixed.y = true;
}
else {
node.x = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId];
node.x = this.options.hierarchical.levelSeparation * level;
node.options.fixed.x = true;
}
if (distribution[this.hierarchicalLevels[nodeId]] === undefined) {
distribution[this.hierarchicalLevels[nodeId]] = {amount: 0, nodes: {}, distance: 0};
if (distribution[level] === undefined) {
distribution[level] = {amount: 0, nodes: {}, distance: 0};
}
distribution[this.hierarchicalLevels[nodeId]].amount += 1;
distribution[this.hierarchicalLevels[nodeId]].nodes[nodeId] = node;
distribution[level].amount += 1;
distribution[level].nodes[nodeId] = node;
}
}
return distribution;
@ -398,6 +400,7 @@ class LayoutEngine {
parentNode = edges[i].from;
}
let childNodeLevel = this.hierarchicalLevels[childNode.id];
if (this.positionedNodes[childNode.id] === undefined) {
// if a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here.
if (childNodeLevel > parentLevel) {

+ 3
- 0
lib/network/modules/components/Node.js View File

@ -119,6 +119,9 @@ class Node {
if (options.x !== undefined) {this.x = options.x; this.predefinedPosition = true;}
if (options.y !== undefined) {this.y = options.y; this.predefinedPosition = true;}
if (options.size !== undefined) {this.baseSize = options.size;}
if (options.label === undefined && this.options.label === undefined) {
this.options.label = this.id;
}
// this transforms all shorthands into fully defined options
Node.parseOptions(this.options,options);

+ 4
- 6
lib/util.js View File

@ -285,11 +285,6 @@ exports.selectiveNotDeepExtend = function (props, a, b) {
* @returns {Object}
*/
exports.deepExtend = function(a, b, protoExtend) {
// TODO: add support for Arrays to deepExtend
if (Array.isArray(b)) {
throw new TypeError('Arrays are not supported by deepExtend');
}
for (var prop in b) {
if (b.hasOwnProperty(prop) || protoExtend === true) {
if (b[prop] && b[prop].constructor === Object) {
@ -303,7 +298,10 @@ exports.deepExtend = function(a, b, protoExtend) {
a[prop] = b[prop];
}
} else if (Array.isArray(b[prop])) {
throw new TypeError('Arrays are not supported by deepExtend');
a[prop] = [];
for (let i = 0; i < b[prop].length; i++) {
a[prop].push(b[prop][i]);
}
} else {
a[prop] = b[prop];
}

Loading…
Cancel
Save