1

Still being rather inexperienced in using d3.js I have hit a road block. Hoping anybody out there can help me.

I am trying to display a picture upon mouse click on a node in a graph. Ideally, I'd like to click on several nodes and display images. Double click on a node should remove the image. And clicking on the background removes all displayed images. But one step at a time.

What I have done so far is: Succeeded in using tooltips. I was also able to change the size of a circle node upon mouse clicking on it.

I used as toy project Mike Bostock's force-directed graph example: https://bl.ocks.org/mbostock/4062045 . I am using d3.js v4

Based on an example on the web I was able to add pictures to all nodes: Add different images for nodes in d3 v4 network graph

I tried to tailor this example to my needs. First I added:

var defs = svg.append('defs');

Further more:

var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter()
.append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); })
.call(node_drag)
.on("click", function(d){
    defs.append("pattern")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 12)
    .attr("height", 12)
    .append("image")
    .attr("xlink:href", 'https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png')
    .attr("width", 12)
    .attr("height", 12)
    .attr("x", 0)
    .attr("y", 0);
})

In my browser the html indicates that the image is added:

image of html

But the image is not showing in the browser.

At this point I am turning to you and hope for some hints how I can accomplish displaying an image as node upon clicking with my mouse cursor on it.

Any input is highly appreciated, Markus

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
Markus
  • 39
  • 5

1 Answers1

1

Your inspector is showing that the image was appended to the pattern, but it was never linked to the circle element.

Instead of appending the pattern to the defs inside the click function, you should just append the pattern with a given ID...

var defs = svg.append('defs');

defs.append("pattern")
    .attr("x", 0)
    .attr("y", 0)
    .attr("id", "myPattern")//ID here
    .attr("width", 12)
    .attr("height", 12)
    .append("image")
    .attr("xlink:href", 'https://assets-cdn.github.com/images/modules/open_graph/github-octocat.png')
    .attr("width", 12)
    .attr("height", 12)
    .attr("x", 0)
    .attr("y", 0);

... and then, inside the click, just change the fill of the circle according to that ID:

.on("click", function() {
    d3.select(this).attr("fill", "url(#myPattern)")
})

Here is Bostock's bl.ocks with those changes (I made the circles bigger so you can better see the image): https://bl.ocks.org/anonymous/0e653b6d21c8d57afa234d5d1765efe0/78ba15e533a2b8f8e6575a30d97b27d156ce2faf

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • 1
    Hello Gerardo: Thank you very much. Your input suggested the following modification: I added for each node an extra defs.append("pattern") section with an id corresponding to the id property in the json file. Next in the mouse click on section I constructed the id from d.id and used is as fill. I also increased the radius. Finally, I created a double click event which chances everything back. I used python to create the index.html file in order to cope with the many sections. All the best, Markus – Markus Oct 15 '17 at 02:14