Closed simov closed 9 years ago
This question still stands. How do I render a new graph using the same setup? Effectively a "wipe" of the current renderer, listeners, events etc.
@danpaulsmith that depends on how you implement your graph(ie. Are your event listeners implemented via the renderer every time a node / link is created or are you using an MVC such as angular to manage event listeners/UI events while the vivagraph instance merely handles default node/link creation) . I can try and help you a bit more if you have a code example
The only events I have are the WebglInputEvents, which are setup in the "set up" phase and some keydown/keyup from the multiselect demo.
I have a drawMap() function which I want to call to multiple times, each time, wiping the canvas and drawing a totally new graph. I'm trying to call renderer.dispose, but it throws an error (TypeError: publicEvents.removeAllListeners is not a function).
var App = {};
function drawMap(results) {
if (App.renderer) {
App.renderer.dispose();
App.graphics.release();
App.graph.clear();
}
App.results = results;
var graph = App.graph = Viva.Graph.serializer().loadFromJSON(results);
var layout = Viva.Graph.Layout.forceDirected(graph, {
springLength: 100,
springCoeff: 0.0005,
dragCoeff: 0.02,
gravity: 0
});
var graphicsOptions = {
clearColor: true, // we want to avoid rendering artifacts
clearColorValue: { // use black color to erase background
r: 0,
g: 0,
b: 0,
a: 1
}
};
var graphics = App.graphics = Viva.Graph.View.webglGraphics(graphicsOptions);
graph.forEachNode(function(node) {
layout.setNodePosition(node.id, node.data.x, node.data.y);
});
graphics.node(function (node) {
return Viva.Graph.View.webglSquare(node.data.size, node.data.color);
});
var renderer = App.renderer = Viva.Graph.View.renderer(graph, {
layout: layout,
graphics: graphics,
renderLinks: false,
container: document.getElementById('graph-container')
});
var multiSelectOverlay;
var events = Viva.Graph.webglInputEvents(graphics, graph);
events.mouseEnter(function (node) {
detailsElement.innerHTML = node.data.title;
document.body.style.cursor = 'pointer';
}).mouseLeave(function (node) {
detailsElement.innerHTML = '';
document.body.style.cursor = 'auto';
}).dblClick(function (node) {
}).click(function (node) {
App.selectNodes([node.id]);
});
renderGraph();
function renderGraph() {
renderer.run();
// Final bit: most likely graph will take more space than available
// screen. Let's zoom out to fit it into the view:
var graphRect = layout.getGraphRect();
var graphSize = Math.min(graphRect.x2 - graphRect.x1, graphRect.y2 - graphRect.y1);
var screenSize = Math.min(document.body.clientWidth, document.body.clientHeight);
var desiredScale = screenSize / graphSize;
zoomOut(desiredScale, 1);
App.rendererGraphics = renderer.getGraphics();
renderer.pause();
renderer.reset();
function zoomOut(desiredScale, currentScale) {
// zoom API in vivagraph 0.5.x is silly. There is no way to pass transform
// directly. Maybe it will be fixed in future, for now this is the best I could do:
if (desiredScale < currentScale) {
currentScale = renderer.zoomOut();
setTimeout(function() {
zoomOut(desiredScale, currentScale);
}, 16);
}
}
}
document.addEventListener('keydown', function(e) {
if (e.which === 16 && !multiSelectOverlay) { // shift key
multiSelectOverlay = startMultiSelect(graph, renderer, layout);
}
});
document.addEventListener('keyup', function(e) {
if (e.which === 16 && multiSelectOverlay) {
multiSelectOverlay.destroy();
multiSelectOverlay = null;
}
});
}
To add to this, if I comment out the line
publicEvents.removeAllListeners();
in vivagraph.js, then I am able to re-render a new graph using the same setup function (drawGraph).
In theory graph.clear()
should completely reset the graph. Then adding new nodes/edges should reuse the same renderer/layout settings. If this doesn't work then we need to find where it's broken.
Doesn't seem to work for me, the visualisation freezes. Here's a simple example:
What do I need to do after using graph.clear() in order to draw a new graph?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>VivaGraphs WebGL Mouse Input test page</title>
<style type='text/css'>
body, #graph-container {
height: 100%;
width: 100%;
position: absolute;
overflow: hidden;
margin: 0px;
}
#loadNew {
margin: 50px;
position: fixed;
left: 0;
top: 0;
z-index: 99999;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/anvaka/VivaGraphJS/master/dist/vivagraph.min.js"></script>
<script type='text/javascript'>
var App = {};
function onLoad() {
App.graphGenerator = Viva.Graph.generator();
App.graph = App.graphGenerator.grid(50, 10);
App.layout = Viva.Graph.Layout.forceDirected(App.graph);
App.graphics = Viva.Graph.View.webglGraphics();
App.renderer = Viva.Graph.View.renderer(App.graph, {
layout: App.layout,
graphics: App.graphics,
container: document.getElementById('graph-container')
});
App.renderer.run();
}
function loadNew() {
App.graph.clear();
App.graph = App.graphGenerator.grid(10, 10);
// ... ?
}
$(document).ready(function() {
$('button#loadNew').click(function() {
console.log('loadNew', App);
loadNew();
});
});
</script>
</head>
<body onload="onLoad()">
<div id="graph-container"></div>
<div class="graph-overlay"></div>
<button id="loadNew">Load new graph</button>
</body>
</html>
Oh, but you are changing the reference to the graph in this line App.graph = App.graphGenerator.grid(10, 10);
. Try copy graph instead:
copyGraph(App.graphGenerator.grid(10, 10), App.graph);
function copyGraph(from, to) {
to.beginUpdate();
from.forEachLink(copyLink);
to.endUpdate();
function copyLink(link) {
to.addLink(link.fromId, link.toId);
}
}
Here is a demo: http://jsbin.com/poduteguyu/1/edit?html,output
Ah okay. My graphs have 50,000 nodes which have their positions precomputed, I thought there must be a way to draw the graph without having to add each node individually. So I'm using loadJSON(). Is the only way to draw a new graph to beginUpdate(), add each node, endUpdate()?
On 14 Feb 2015, at 20:47, Andrei Kashcha notifications@github.com wrote:
Oh, but you are changing the reference to the graph in this line App.graph = App.graphGenerator.grid(10, 10);. Try copy graph instead:
copyGraph(App.graphGenerator.grid(10, 10), App.graph);
function copyGraph(from, to) { to.beginUpdate(); from.forEachLink(copyLink); to.endUpdate(); function copyLink(link) { to.addLink(link.fromId, link.toId); } } Here is a demo: http://jsbin.com/poduteguyu/1/edit?html,output
— Reply to this email directly or view it on GitHub.
Hi, thanks for this great library! I have a question about a topic that's not covered in the examples.
I'm trying to recreate the entire scene dynamically without reloading the page. Here is what I do:
After that on some user interaction when new JSON arrived I'm making this:
Although this technique works it has some odd side effects. After refresh on dragging the scene it start to have some offset and moves really fast. The worst is that the animation is active for only a few seconds after that if I drag a node, the rest of the scene is not moving like in the
constantLayout.html
example.What is the proper way to recreate the entire scene dynamically?
Thanks