Browse Source

Finalized import, reduced needless drawing of the network (performance boost!)

v3_develop
Alex de Mulder 10 years ago
parent
commit
09d3f83ab6
10 changed files with 28309 additions and 28049 deletions
  1. +8
    -0
      HISTORY.md
  2. +15224
    -15147
      dist/vis-light.js
  3. +12925
    -12848
      dist/vis.js
  4. +2
    -1
      examples/network/29_neighbourhood_highlight.html
  5. +106
    -24
      examples/network/30_importing_from_gephi.html
  6. +2
    -0
      examples/network/index.html
  7. +2
    -1
      index.js
  8. +8
    -6
      lib/network/Network.js
  9. +23
    -22
      lib/network/gephiParser.js
  10. +9
    -0
      lib/util.js

+ 8
- 0
HISTORY.md View File

@ -35,6 +35,14 @@ http://visjs.org
- Added borderWidth option for nodes.
- Implemented new Hierarchical view solver.
- Fixed an issue with selecting nodes when the web page is scrolled down.
- Added Gephi JSON parser
- Added Neighbour Highlight example
- Added Import From Gephi example
- Enabled color parsing for nodes when supplied with rgb(xxx,xxx,xxx) value.
### DataSet
- Added .get() returnType option to return as JSON object, Array or Google DataTable.

+ 15224
- 15147
dist/vis-light.js
File diff suppressed because it is too large
View File


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


+ 2
- 1
examples/network/29_neighbourhood_highlight.html View File

@ -18,10 +18,11 @@
<body>
<h2>Dynamic Data - Neighbourhood Highlight</h2>
<div style="width:700px; font-size:14px;">
<div style="width:800px; font-size:14px;">
This example shows the power of the DataSet. Once a node is clicked, all nodes are greyed out except for the first and second order connected nodes.
In this example we show how you can determine the order of connection per node as well as applying individual styling to the nodes based on whether or not
they are connected to the selected node. The code doing the highlighting only takes about 20ms, the rest of the time is the redrawing of the network (9200 edges..).
<br /><br />
</div>
<div id="mynetwork"></div>

+ 106
- 24
examples/network/30_importing_from_gephi.html View File

@ -1,8 +1,7 @@
<!DOCTYPE html>
<!-- saved from url=(0044)http://kenedict.com/networks/worldcup14/vis/ , thanks Andre!-->
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF8">
<title>Network | Static smooth curves - World Cup Network</title>
<title>Dynamic Data - Importing from Gephi (JSON)</title>
<script type="text/javascript" src="../../dist/vis.js"></script>
<link type="text/css" rel="stylesheet" href="../../dist/vis.css">
@ -12,37 +11,58 @@
height: 800px;
border: 1px solid lightgray;
}
div.nodeContent {
position: relative;
border: 1px solid lightgray;
width:480px;
height:780px;
margin-top: -802px;
margin-left: 810px;
padding:10px;
}
pre {padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
</style>
</head>
<body>
<h2>Dynamic Data - Neighbourhood Highlight</h2>
<div style="width:700px; font-size:14px;">
This example shows the power of the DataSet. Once a node is clicked, all nodes are greyed out except for the first and second order connected nodes.
In this example we show how you can determine the order of connection per node as well as applying individual styling to the nodes based on whether or not
they are connected to the selected node. The code doing the highlighting only takes about 20ms, the rest of the time is the redrawing of the network (9200 edges..).
<h2>Dynamic Data - Importing from Gephi (JSON)</h2>
<div style="width:900px; font-size:14px;">
This example shows how to import a JSON file exported by Gephi. The two options available for the import are
available through the checkboxes. You can download the Gephi JSON exporter here:
<a href="https://marketplace.gephi.org/plugin/json-exporter/" target="_blank">https://marketplace.gephi.org/plugin/json-exporter/</a>.
All of Gephi's attributes are also contained within the node elements. This means you can access all of this data through the DataSet. An example of this is shown next to the network.
<br /><br />
</div>
<input type="checkbox" id="allowedToMove">: Allow to move after import. <br/>
<input type="checkbox" id="parseColor">: Parse the color instead of copy (adds borders, highlights etc.)
<div id="mynetwork"></div>
<div class="nodeContent"><h4>Node Content:</h4> <pre id="nodeContent"></pre></div>
<script type="text/javascript">
var network;
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var network;
function redrawAll() {
nodes.clear();
edges.clear();
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var gephiImported;
var allowedToMoveCheckbox = document.getElementById("allowedToMove");
allowedToMoveCheckbox.onchange = redrawAll;
network = null;
// create an array with nodes
var parseColorCheckbox = document.getElementById("parseColor");
parseColorCheckbox.onchange = redrawAll;
var nodeContent = document.getElementById("nodeContent");
nodes.add(nodesData);
edges.add(edgesData);
loadJSON("./data/WorldCup2014.json",redrawAll);
var container = document.getElementById('mynetwork');
var data = {
@ -52,9 +72,6 @@ function redrawAll() {
var options = {
nodes: {
shape: 'dot',
radiusMin: 10,
radiusMax: 30,
fontSize: 12,
fontFace: "Tahoma"
},
edges: {
@ -70,15 +87,80 @@ function redrawAll() {
},
smoothCurves: {dynamic:false, type: "continuous"},
stabilize: false,
physics: {barnesHut: {gravitationalConstant: 0, centralGravity: 0, springConstant: 0}},
physics: {barnesHut: {gravitationalConstant: -10000, springConstant: 0.002, springLength: 150}},
hideEdgesOnDrag: true
};
network = new vis.Network(container, data, options);
/**
* This function fills the DataSets. These DataSets will update the network.
*/
function redrawAll(gephiJSON) {
// only have to get the JSON from the file once
if (gephiJSON.nodes === undefined) {
gephiJSON = gephiImported;
}
else {
gephiImported = gephiJSON;
}
// empty the DataSets
nodes.clear();
edges.clear();
var allowedToMove = allowedToMoveCheckbox.checked;
var parseColor = parseColorCheckbox.checked;
var parsed = vis.network.gephiParser.parseGephi(gephiJSON, {allowedToMove:allowedToMove, parseColor:parseColor});
// add the parsed data to the DataSets.
nodes.add(parsed.nodes);
edges.add(parsed.edges);
var data = nodes.get(2); // get the data from node 2
nodeContent.innerHTML = syntaxHighlight(data); // show the data in the div
network.zoomExtent(); // zoom to fit
}
// from http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript
function syntaxHighlight(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
redrawAll()
function loadJSON(path, success, error) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
success(JSON.parse(xhr.responseText));
}
else {
error(xhr);
}
}
};
xhr.open("GET", path, true);
xhr.send();
}
</script>

+ 2
- 0
examples/network/index.html View File

@ -40,6 +40,8 @@
<p><a href="26_staticSmoothCurves.html">26_staticSmoothCurves.html</a></p>
<p><a href="27_world_cup_network.html">27_world_cup_network.html</a></p>
<p><a href="28_world_cup_network_performance.html">28_world_cup_network_performance.html</a></p>
<p><a href="29_neighbourhood_highlight.html">29_neighbourhood_highlight.html</a></p>
<p><a href="30_importing_from_gephi.html">30_importing_from_gephi.html</a></p>
<p><a href="graphviz/graphviz_gallery.html">graphviz_gallery.html</a></p>
</div>

+ 2
- 1
index.js View File

@ -55,7 +55,8 @@ exports.network = {
Images: require('./lib/network/Images'),
Node: require('./lib/network/Node'),
Popup: require('./lib/network/Popup'),
dotparser: require('./lib/network/dotparser')
dotparser: require('./lib/network/dotparser'),
gephiParser: require('./lib/network/gephiParser')
};
// Deprecated since v3.0.0

+ 8
- 6
lib/network/Network.js View File

@ -1064,7 +1064,7 @@ Network.prototype._handleOnDrag = function(event) {
Network.prototype._onDragEnd = function () {
this.drag.dragging = false;
var selection = this.drag.selection;
if (selection) {
if (selection && selection.length) {
selection.forEach(function (s) {
// restore original xFixed and yFixed
s.node.xFixed = s.xFixed;
@ -1073,7 +1073,10 @@ Network.prototype._onDragEnd = function () {
this.moving = true;
this.start();
}
this._redraw();
else {
this._redraw();
}
};
/**
@ -2124,10 +2127,10 @@ Network.prototype._discreteStepNodes = function() {
*/
Network.prototype._physicsTick = function() {
if (!this.freezeSimulation) {
if (this.moving) {
if (this.moving == true) {
this._doInAllActiveSectors("_initializeForceCalculation");
this._doInAllActiveSectors("_discreteStepNodes");
if (this.constants.smoothCurves) {
if (this.constants.smoothCurves.enabled == true && this.constants.smoothCurves.dynamic == true) {
this._doInSupportSector("_discreteStepNodes");
}
this._findCenter(this._getRange())
@ -2161,7 +2164,6 @@ Network.prototype._animationStep = function() {
timeRequired = Date.now() - calculationTime;
maxSteps++;
}
// start the rendering process
var renderTime = Date.now();
this._redraw();
@ -2178,7 +2180,7 @@ if (typeof window !== 'undefined') {
* Schedule a animation step with the refreshrate interval.
*/
Network.prototype.start = function() {
if (this.moving || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0) {
if (this.moving == true || this.xIncrement != 0 || this.yIncrement != 0 || this.zoomIncrement != 0) {
if (!this.timer) {
var ua = navigator.userAgent.toLowerCase();

+ 23
- 22
lib/network/gephiParser.js View File

@ -4,52 +4,53 @@ function parseGephi(gephiJSON, options) {
var nodes = [];
this.options = {
edges: {
inheritColor: 'from'
inheritColor: true
},
nodes: {
allowedToMove: false,
parseColor: false
}
};
if (options !== undefined) {
this.options.edges['inheritColor'] = options.inheritColor | 'from';
this.options.nodes['allowedToMove'] = options.allowedToMove | false;
this.options.nodes['parseColor'] = options.parseColor | false;
this.options.edges['inheritColor'] = options.inheritColor | true;
}
var gEdges = gephiJSON.edges;
var gNodes = gephiJSON.nodes;
for (var i = 0; i < gEdges.length; i++) {
var edge = {};
edge['id'] = gEdges.id;
edge['from'] = gEdges.source;
edge['to'] = gEdges.target;
edge['attributes'] = gEdges.attributes;
edge['value'] = gEdges.attributes !== undefined ? gEdges.attributes.Weight : undefined;
edge['width'] = gEdges.size;
edge['color'] = gEdges.color;
var gEdge = gEdges[i];
edge['id'] = gEdge.id;
edge['from'] = gEdge.source;
edge['to'] = gEdge.target;
edge['attributes'] = gEdge.attributes;
// edge['value'] = gEdge.attributes !== undefined ? gEdge.attributes.Weight : undefined;
// edge['width'] = edge['value'] !== undefined ? undefined : edgegEdge.size;
edge['color'] = gEdge.color;
edge['inheritColor'] = edge['color'] !== undefined ? false : this.options.inheritColor;
edges.push(edge);
}
for (var i = 0; i < gNodes.length; i++) {
var node = {};
node['id'] = gNodes.id;
node['attributes'] = gNodes.attributes;
node['x'] = gNodes.x;
node['y'] = gNodes.y;
node['label'] = gNodes.label;
if (this.options.parseColor == true) {
node['color'] = gNodes.color;
var gNode = gNodes[i];
node['id'] = gNode.id;
node['attributes'] = gNode.attributes;
node['x'] = gNode.x;
node['y'] = gNode.y;
node['label'] = gNode.label;
if (this.options.nodes.parseColor == true) {
node['color'] = gNode.color;
}
else {
node['color'] = gNodes.color !== undefined ? {background:gNodes.color, border:gNodes.color} : undefined;
node['color'] = gNode.color !== undefined ? {background:gNode.color, border:gNode.color} : undefined;
}
node['radius'] = gNodes.size;
node['allowedToMoveX'] = this.options.allowedToMove;
node['allowedToMoveY'] = this.options.allowedToMove;
node['shape'] = 'dot'
node['radius'] = gNode.size;
node['allowedToMoveX'] = this.options.nodes.allowedToMove;
node['allowedToMoveY'] = this.options.nodes.allowedToMove;
nodes.push(node);
}

+ 9
- 0
lib/util.js View File

@ -753,6 +753,10 @@ exports.GiveHex = function(Dec) {
exports.parseColor = function(color) {
var c;
if (exports.isString(color)) {
if (exports.isValidRGB(color)) {
var rgb = color.substr(4).substr(0,color.length-5).split(',');
color = exports.RGBToHex(rgb[0],rgb[1],rgb[2]);
}
if (exports.isValidHex(color)) {
var hsv = exports.hexToHSV(color);
var lighterColorHSV = {h:hsv.h,s:hsv.s * 0.45,v:Math.min(1,hsv.v * 1.05)};
@ -930,6 +934,11 @@ exports.isValidHex = function(hex) {
return isOk;
};
exports.isValidRGB = function(rgb) {
rgb = rgb.replace(" ","");
var isOk = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/i.test(rgb);
return isOk;
}
/**
* This recursively redirects the prototype of JSON objects to the referenceObject

Loading…
Cancel
Save