Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG markers don't orient properly on a d3.svg.diagonal curve used as a D3 force layout link

I'm a bit new to SVG and d3.js.

While drawing a graph with D3 force layout, I'm using a simple diagonal line generator and using marker-end to draw arrow heads.

When using arc instead of diagonal generator the arrow heads appear just fine. But using diagonal generator like in the code below doesn't produce proper markers:

var vis = this.vis = d3.select(el).append("svg:svg")
    .attr("width", w)
    .attr("height", h);

var force = d3.layout.force()
    .gravity(0.03)
    .distance(120)
    .charge(-800)
    .size([w, h]);

var linkDiag = d3.svg.diagonal()
    .projection(function(d)
    {
        return [d.x, d.y];
    });

vis.append("svg:defs")
        .selectAll("marker")
    .data(["normal", "special", "resolved"])
   .enter()
        .append("svg:marker")
    .attr("id", String)
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 15)
    .attr("refY", -1.5)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
    .append("svg:path")
    .attr("d", "M 0,-5 L 10,0 L0,5");

...and then also:

    force.on("tick", function() {
        link.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("d", linkDiag)
        .attr("marker-end", function(d) { return "url(#special)"; });

    });

The markers are not oriented at all with the vertices.

Any help would be appreciated!

like image 561
ronnen Avatar asked May 23 '12 11:05

ronnen


People also ask

What is SVG elements in D3?

In this chapter, we will learn about creating SVG elements using D3. SVG provides different shapes like lines, rectangles, circles, ellipses etc. Hence, designing visualizations with SVG gives you more flexibility and power in what you can achieve.

How to use data bound to DOM elements in SVG circle?

In the Use Data Bound To DOM Elements With D3.js section, we used the bound data the following way: With the key to using the bound data, being the JavaScript function: D3.js lets us use this same function to alter the parameters used in building the SVG Circle!

How to set the orientation of a D3 axis?

The d3.axis.orient () Function in D3.js is used to set the orientation and returns the axis. If the orientation is not specified, returns the current orientation which defaults to “bottom”. Parameters: This function accepts a single parameter as mentioned above and described below:

What is an SVG circle element?

An SVG Circle Element is a basic SVG shape element. Basic shape elements are standard shapes which are pre-defined in SVG. Note - they can be recreated mathematically using a path (which we'll see later). For now, you will use the basic SVG shape element.


1 Answers

It only appears as if the arrows aren't pointing in the right direction because you're moving the arrowhead to a new position via refX and refY.

For example, check out this code which draws diagonals in various directions. The arrowheads appear correctly, with the exception of the one at 180 degrees, but that's probably due to a rounding error.

Now, try changing refX on line 10 to a value of, say, 5. Now, the arrowheads close to the horizontal appear incorrect. To see this more dramatically, try changing the value to 8.

What's happening is you're hiding part of the diagonal so the line appears to be ending at an earlier point, which is curved slightly differently from the actual end-point. The same thing will happen if the arrowhead is too large so that it overlays part of the curve. Note that for diagonals in d3, which are symmetrical bezier curves, the arrowheads should always appear pointing perfectly horizontally or vertically. You can see exactly what's happening by reducing the arrowhead's opacity.

like image 177
Yony Avatar answered Nov 26 '22 06:11

Yony