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

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

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

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

@ -159,6 +159,7 @@ class LayoutEngine {
this._determineLevelsDirected(); this._determineLevelsDirected();
} }
} }
// check the distribution of the nodes per level. // check the distribution of the nodes per level.
let distribution = this._getDistribution(); let distribution = this._getDistribution();
@ -177,7 +178,6 @@ class LayoutEngine {
_placeNodesByHierarchy(distribution) { _placeNodesByHierarchy(distribution) {
let nodeId, node; let nodeId, node;
this.positionedNodes = {}; this.positionedNodes = {};
// start placing all the level 0 nodes first. Then recursively position their branches. // start placing all the level 0 nodes first. Then recursively position their branches.
for (let level in distribution) { for (let level in distribution) {
if (distribution.hasOwnProperty(level)) { if (distribution.hasOwnProperty(level)) {
@ -185,6 +185,7 @@ class LayoutEngine {
if (distribution[level].nodes.hasOwnProperty(nodeId)) { if (distribution[level].nodes.hasOwnProperty(nodeId)) {
node = distribution[level].nodes[nodeId]; node = distribution[level].nodes[nodeId];
if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") { if (this.options.hierarchical.direction === "UD" || this.options.hierarchical.direction === "DU") {
if (node.x === undefined) {node.x = distribution[level].distance;} if (node.x === undefined) {node.x = distribution[level].distance;}
distribution[level].distance = node.x + this.nodeSpacing; distribution[level].distance = node.x + this.nodeSpacing;
@ -218,19 +219,20 @@ class LayoutEngine {
for (nodeId in this.body.nodes) { for (nodeId in this.body.nodes) {
if (this.body.nodes.hasOwnProperty(nodeId)) { if (this.body.nodes.hasOwnProperty(nodeId)) {
node = this.body.nodes[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") { 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; node.options.fixed.y = true;
} }
else { else {
node.x = this.options.hierarchical.levelSeparation * this.hierarchicalLevels[nodeId];
node.x = this.options.hierarchical.levelSeparation * level;
node.options.fixed.x = true; 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; return distribution;
@ -398,6 +400,7 @@ class LayoutEngine {
parentNode = edges[i].from; parentNode = edges[i].from;
} }
let childNodeLevel = this.hierarchicalLevels[childNode.id]; let childNodeLevel = this.hierarchicalLevels[childNode.id];
if (this.positionedNodes[childNode.id] === undefined) { 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 a node is conneceted to another node on the same level (or higher (means lower level))!, this is not handled here.
if (childNodeLevel > parentLevel) { 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.x !== undefined) {this.x = options.x; this.predefinedPosition = true;}
if (options.y !== undefined) {this.y = options.y; this.predefinedPosition = true;} if (options.y !== undefined) {this.y = options.y; this.predefinedPosition = true;}
if (options.size !== undefined) {this.baseSize = options.size;} 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 // this transforms all shorthands into fully defined options
Node.parseOptions(this.options,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} * @returns {Object}
*/ */
exports.deepExtend = function(a, b, protoExtend) { 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) { for (var prop in b) {
if (b.hasOwnProperty(prop) || protoExtend === true) { if (b.hasOwnProperty(prop) || protoExtend === true) {
if (b[prop] && b[prop].constructor === Object) { if (b[prop] && b[prop].constructor === Object) {
@ -303,7 +298,10 @@ exports.deepExtend = function(a, b, protoExtend) {
a[prop] = b[prop]; a[prop] = b[prop];
} }
} else if (Array.isArray(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 { } else {
a[prop] = b[prop]; a[prop] = b[prop];
} }

Loading…
Cancel
Save