D3 multiple drag handlers - javascript

Is it possible to have more than one element with a .call(drag) on it in a force graph?
In my example I have <circle/>s and <rect/>s. The <circle/>s are part of my force simulation and the <rect/>s are not. I would like to be able to drag both of them, using separate drag handlers of course. The <circle/>s are draggable but the <rect/>s are not. According to some examples I've found it seems totally possible to have a drag event that is not part of a force simulation. But I have no evidence of them working in tandem.
Related fiddle:
The circular nodes are draggable but the squares in the top left of the graph are not.
How can I make both of them draggable? I do not want the squares as part of the simulation as I do not want the forces applied to them.
https://jsfiddle.net/jrymer/ftv94rzk/53/

Seems even though the simulation does not use the data, I still need to respect the simulation's internal timer and use it's tick function to reposition as I drag. I have update the original fiddle to reflect this. The rectangles I added do not effect the nodes force wise, but can still be dragged, which was my goal.

Related

How to detect a node in one graph being dragged over another?

Drawing node/edge graphs in Vis.js-network, I want to have two graphs graphDrag and graphStatic: where the user can drag the nodes of graphDrag around the canvas, while graphStatic remains fixed in place, so that the user can attach the graphDrag nodes to the nodes of graphStatic; the idea is for the user to be able to check whether graphStatic is a subgraph of graphDrag.
I didn't see anything in the Vis.js documentation about listening for an event where one node gets dragged onto another, or sticking nodes to each other. I know that I can do my own event handling by checking for overlap between the screen positions of graphDrag and graphStatic nodes, and then presumably changing the fixed property of the graphDrag node when they overlap, but I'm hoping that this functionality already exists somewhere. Is this possible in Vis.js, or is there a different graph visualization SDK that would be more appropriate?
Edit: I've also tried using Cytoscape.js but that doesn't seem to have this functionality built-in either.

Dygraphs - Create a Chart with "draggable" points

Was wondering if there is a way in the dygraphs to enable draggable points in the sense that when a graph has been generated the user can drag (down or up) a specific point in the graph and the graph will adjust accordingly ?
Is there a way to emulate such a behaviour in Dygraphs ? Haven't found any information about that.
This is possible, but there's no out-of-the-box support for it. You'd have to write your own interaction model to catch the initial mousedown event and subsequent mousemove and mouseup events. You'd probably implement this by changing the underlying chart data during the drag.
Note that click+drag already has a meaning in dygraphs: it zooms the chart.

Updating node labels to avoid clutter in JavaScript InfoVis Toolkit (JIT)

I am doing visualization with the JavaScript InfoVis Toolkit, in particular the hypertree. I am loading data dynamically and sometimes the labels around the nodes overlap and clutter. I would like to avoid this clutter by altering the label positions.
Here is an example of cluttering (the top and bottom nodes):
I imagine that I would loop through each x,y coordinate, give it some bounding box and do basic collision detection, and update positions accordingly.
For this library, I see the demo shows a onPlaceLabel() function, but (if I understand correctly) at that moment I wouldn't know the position of every other node's label. So, I am looking at onComplete(), where I see I can access each node as follows:
onComplete: function(){
ht.graph.eachNode(function(n) {
console.log(n);
}
}
But the node information does not include its label positions, only their positions relative to the center node. Is there a way to access the labels in this way and be able to update their positions?

Understanding "call" in D3.js with force-directed layouts

I am new to D3.js, and I want to work with graph layouts. I have this demo set up with a very simple graph obeying the force-directed layout built into D3.
http://jsfiddle.net/ewG95/
What I want to do is be able to turn off the graph layout algorithm (say, when the user presses space) and then still be able to drag nodes around, and turn the force-directed layout back on later.
Right now I have it set up to stop the force-directed layout upon hitting space:
d3.select("body")
.on("keydown", function() {
if (d3.event.keyCode == 32) {
if (forceActive) {force.stop();} else {force.resume();}
}
});
The problem is that every time you drag a node it restarts the force-layout. I've narrowed it down to (essentially) that the call method on a node is being bound to the force layout's drag method.
i.e. this piece of the linked code:
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("circle")
...
.call(force.drag);
I imagine I may have to do two things:
Write a custom "drag" method that moves a node and the edges associated to a single node.
Rebind the node's call method to it as needed (does this even make sense? Would that replace the bound method? And what does force.drag really do?).
I want to know if this has been done before, and how to do it (at all, possibly not using my guess as to how to do it).
First, on your explicit question: what does the call() method do?
In d3, call is just a convenience function to turn other functions inside out. Doing
node.call( force.drag );
Is actually just the same as doing
force.drag( node );
The only difference is that the call method on a selection always returns the selection so you can chain other methods to it.
So now your question is, what does the force.drag( selection ) do? It creates the event listeners that handle the mouse and touch events for the drag behaviour. Those event listeners update the position of the node data object, but they also restart the force layout.
If you don't want the default force-layout drag behaviour, just don't call the force.drag method on your selection.
As far as being able to customize the drag behaviour so that it doesn't restart the force layout, it doesn't look like you can do it with force.drag (not without changing the source code, anyway). However, you can access most of the drag-related functionality by creating your own drag behaviour object and binding it to the nodes.
Then, in your drag event handler you would update the x and y positions of the node data object, and redraw the node and any links attached to it. If your graph isn't too big, you can do this by re-calling your tick function to redraw all the elements to match their data; if your graph is big, you might want to store references to the actual elements in the data objects so you can quickly find the correct links.
Some examples on using drag behaviours (without force layout) to get you started:
http://bl.ocks.org/mbostock/1557377
http://bl.ocks.org/mccannf/1629464
http://bl.ocks.org/mbostock/6123708

Adding sizing handles to drawn object in canvas

I have a full screen canvas I am drawing to, and I've set it up to allow the user to drag and drop objects that are within the canvas.
I also want to enable them to select an object, and then 'resize handlers' show up (the little circles in the corners) to allow them to click/drag and resize them.
I can code this manually by drawing circles in each corner and detect a click, etc.... but was wondering if anyone has any better way to do this? Maybe there's a library out there that already handles this?
Any help is appreciated!
There isn't any simpler way than doing it yourself or getting a library to do it for you.
I wrote a tutorial here on the use of sizing handles. That should get you started if you plan to make your own.

Categories

Resources