Changing an arrowhead interactively

Showing 1-9 of 9 messages
Changing an arrowhead interactively JeffH 11/18/11 12:12 PM
Hi all,

I've been trying to change the color of a link and its arrowhead when
the user clicks on my force graph. So far, I've been successful in
changing the link line but can't figure out how to change the
arrowhead. This is the line in the code below that I thought might
work but doesn't:

d3.select(this.arrowhead).style("fill","red");

Any ideas would be most appreciated!
Thanks,
Jeff

          var link = vis.selectAll("line.link")
              .data(json.links)
            .enter().append("svg:line")
              .attr("class", "link")
              .style("stroke-width", function(d) { return
Math.sqrt(d.value); })
              .attr("x1", function(d) { return d.source.x; })
              .attr("y1", function(d) { return d.source.y; })
              .attr("x2", function(d) { return d.target.x; })
              .attr("y2", function(d) { return d.target.y; })
              .attr("marker-end", "url(#arrowhead)")
              .on("click", function(d) {
                              link.style("stroke","gray");
                              d3.select(this).style("stroke","red");
                              d3.select(this).style("fill","red");
                              d3.select(this.marker).style("fill","red");
                              clickLink(d);
                              });


                defs.append("svg:marker")
                                .attr("id", "arrowhead")
                                .attr("viewBox","0 0 10 10")
                                .attr("refX","20")
                                .attr("refY","5")
                                .attr("markerUnits","strokeWidth")
                                .attr("markerWidth","9")
                                .attr("markerHeight","5")
                                .attr("orient","auto")
                                .append("svg:path")
                                .attr("d","M 0 0 L 10 5 L 0 10 z")
                                .attr("fill", "#BBBBBB");

Re: Changing an arrowhead interactively Mike Bostock 11/18/11 12:54 PM
> d3.select(this.arrowhead).style("fill","red");

Did you mean d3.select("#arrowhead")?

Mike

Re: Changing an arrowhead interactively JeffH 11/18/11 1:33 PM
Sorry Mike... I think my last reply went to you email.

I just need to change the arrowhead of the selected link. I tried:

d3.select("#arrowhead").style("fill","red");
and
d3.this.select("#arrowhead").style("fill","red");
without success...
Re: Changing an arrowhead interactively Mike Bostock 11/18/11 1:45 PM
You have to select the path element within the marker, not the marker
itself. So, "#arrowhead path".

Mike

Re: Changing an arrowhead interactively JeffH 11/18/11 2:01 PM
d3.select("#arrowhead path").style("fill","red");

That works but selects all markers... I can't figure out how to change
just the current (clicked) one.

Thanks for your help!
Re: Changing an arrowhead interactively Mike Bostock 11/18/11 2:03 PM
> That works but selects all markers... I can't figure out how to change
> just the current (clicked) one.

You can't. You have to have a different marker if you want different
colors. I believe a future version of SVG will allow the marker to
inherit the fill and stroke from the associated path, but that's not
currently the case.

Mike

Re: Changing an arrowhead interactively JeffH 11/18/11 2:05 PM
Ah, so I would have to remove this marker for the selected one and
then add another? If you could show me an example, that would be
fantastic! I'm still trying to wrap my head around how you reference
these things.

Cheers,
Jeff
Re: Changing an arrowhead interactively Erick Katzenstein 4/11/14 3:00 PM
Here's kind of a hack that's working for me:
If the script is within a loop, i iterating:

 defs.append("svg:marker") 
                                .attr("id", "arrowhead"+i)         //create unique id for each arrowhead

  var link = vis.selectAll("line.link") 
              .data(json.links) 
            .enter().append("svg:line") 
              .attr("marker-end", "url(#arrowhead"+i+")")   //assign unique arrowhead to each object

 d3.selectAll("#arrowhead"+i+" path")  //select individual arrowhead to change color
Re: Changing an arrowhead interactively reko91 1/7/15 6:00 AM
Similar to what was said by Erick Katzenstein, you have to give each marker a unique ID/name so you can give that one the attribute you want.
Here is how I did it:

defs.append("svg:marker") .attr("id", function(d){ return 'arrow_' + d.name}) //-notice instead of "arrowhead" + i, I created a function to give each arrow a unique ID/name from the data. In my JSON file each edge has a name

For me I was giving it a color from a color scale so when selecting it I selected the path:

var arrows = inner.selectAll("path")
.style('stroke', function(d) { return color(d.name)}); //-colour marker depending on what name it has

This will colour every path so you need to figure out how to select each arrow like Erick did :  d3.selectAll("#arrowhead"+i+" path")  

But that doesnt work, not too sure myself how to do a function in a selectAll();