Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Select Marker Shape for Nodes/Edges #10

Open
JohnOmernik opened this issue Jul 24, 2022 · 14 comments
Open

Feature Request: Select Marker Shape for Nodes/Edges #10

JohnOmernik opened this issue Jul 24, 2022 · 14 comments
Labels
enhancement New feature or request

Comments

@JohnOmernik
Copy link

Via Node/Edge, it would be nice to be able to select a few more marker shapes. I am not strong enough in JS to understand this, but I believe it is possible with SVG markers based on this link:

http://bl.ocks.org/dustinlarimer/5888271

I think this is where directed edge arrows come from, and it would be great if we could select from a few basic shapes like circle (Default as it currently is), Square, Triangle, Diamond, Star. This would give us the ability to have a great selection of nodes and edge shapes to work with, without having to do custom images. (While interesting, SVG shapes makes everything play well I think).

A stretch goal for this request would be the ability to select a Marker and Color and create a definition that can be displayed as a Key. It wouldn't need to be complicated, it could work something like this:

d3_toc = {
                  ('circle', 'black'): "Actors",
                  ('triangle', 'blue'): "Movies",
                  ('square', ''yellow'): "TV Series"
}

and then that could be passed to an optional ToC that gets displayed on the HTML. In addition to the markers shape/color the ability to put just lines of text would be good. You could have the ToC and then you could say "Node Sizes indicate popularity" or "Edge Widths determine number of roles". It would be a manual thing, but the ability to have a few extra shapes, as well as some notes on what we are seeing would look fantastic.

@erdogant
Copy link
Owner

erdogant commented Aug 1, 2022

I am going to look into this.

@erdogant
Copy link
Owner

erdogant commented Sep 3, 2022

I added the feature and it is now possible to change the marker-end!
See docs here.

Note that the marker-start and marker-colors are also in this version but are still under development.

@JohnOmernik
Copy link
Author

This looks pretty great, if I am reading the docs correct at this point, it only applies to Edges correct? Are Node shapes (other than Circle) going to be something that we could change too? Thank you!

@erdogant
Copy link
Owner

erdogant commented Sep 6, 2022

Correct. Edges can now have the marker-end: arrow, stub, circle and square.

@JohnOmernik
Copy link
Author

Would it be possible to use a basic set of shapes for nodes? Are we locked into circles?

@erdogant erdogant added the enhancement New feature or request label Jan 16, 2023
@erdogant
Copy link
Owner

erdogant commented Jan 20, 2023

I did another attempt.. For some reason, it keeps failing when I implement something else and than circles.

@jjon
Copy link

jjon commented Jan 24, 2023

I've only just discovered your d3graph project and I'm hoping it will turn out to be the tool I've needed.

With respect to node shapes: I've recently been trying to learn to use d3.js And I too have wanted to use something other than circles for force directed graphs. I've had some success with this ellipse-force module. It hasn't been updated in a long while, and there's a problem with displaying markers, but I'm keen on ellipses, and hope to expand on their use in directed graphs. Here you can see a toy example of my progress so far.

@erdogant
Copy link
Owner

erdogant commented Mar 18, 2023

This is very cool @jjon! Can you explain how you created the function to drag a node and freeze it (until click again)? Or would it be possible to add this functionality here too? That would help to fix issue #18 :-)

@jjon
Copy link

jjon commented Mar 19, 2023

@erdogant The click and drag behavior of nodes was the product of a lot of naive trial and error and some "monkey see monkey do" from the observablehq.com example mentioned in the comment, so I can't claim to really understand what's going on. I had to do quite a bit of futzing about to get old examples to work with d3.v7; but, this works in the toy example I mentioned:

the d3 for the nodes includes a .call(d.drag()) and looks like this:

var node = svg.append("g")
  .attr("class", "node")
  .selectAll("ellipse")
  .data(dnodes)
  .join(enter => enter.append("ellipse"))
    .attr("rx", function(d) { return d.rx; })
    .attr("ry", function(d) { return d.ry; })
    .attr("fill", function(d) { return type_attributes[d.types[0]].color })
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended))
    .on("click", clicked)
    .on("contextmenu", cmdclick);

and the drag handlers look like this:

//getting rid of d3.event.active fixed the dragging for v7
//see:https://observablehq.com/@d3/d3v6-migration-guide#events
function dragstarted(event, d) {
  if (!event.active) simulation.alphaTarget(0.05).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(event, d) {
  d.fx = event.x;
  d.fy = event.y;
}

function dragended(event, d) {
  if (!event.active) simulation.alphaTarget(0);
  d.fx = event.x;
  d.fy = event.y;
}

this fixes the node at the drag "end" location: d.fx = event.x

and the .on("click", clicked) handler looks like this:

function clicked(event, d) {
    d.fx = null;
    d.fy = null;
}

setting the fixed node location (d.fx & d.fy) back to null

The result is that you can make nodes stay where you drag them until they're clicked. A nice side-effect is that my metadata table, generated in the cmdclick handler, stays with the node when you drag it.

If you come up with any insights on how to make the markers respect the perimeter of the ellipses, do let me know.

Jon

@erdogant
Copy link
Owner

Thanks! I experimented with your code but I can not get the nodes sticky. I must be missing something here.

@jjon
Copy link

jjon commented Mar 19, 2023

@erdogant can you show me the code you're working with?

@erdogant
Copy link
Owner

erdogant commented Mar 19, 2023

See here. Look at the "view page source". If you search for "STICKY NODES" you will find your functions. I needed to change some of the function names. Perhaps it is because I use d3.v3.js whereas you d3.v7? I guess the latter is the issue.

@jjon
Copy link

jjon commented Mar 19, 2023

I'm sure that's it. d3's gone through a lot of breaking changes since d3v3. The observable document here describes how the handling of mouse events has changed since v6. I think, however, that d3.event was available in v3. In v7, the event is passed as a parameter to the drag handlers, so your dragged_node(event, d), for example, won't work under v3. But, it might be as simple as revising it something like this:

function dragged_node(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

But of course, that's probably just wishful thinking. Have a look at Bostock's 'Les Miserables' example that uses d3.v4. There he codes the drag handlers thus:

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

@erdogant
Copy link
Owner

Here is another great example with sticky nodes and with a legend :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants