d3js arrowheads not showing

2020-02-14 10:02发布

I have an example of force directed graph. And i want to show arrowheads, but no matter what i tried i can't see them.

Here is my javascript

    var nodes = {};

    // Compute the distinct nodes from the links.
    links.forEach(function(link) {
        link.source = nodes[link.source] || (nodes[link.source] = {
            name: link.source
        });
        link.target = nodes[link.target] || (nodes[link.target] = {
            name: link.target
        });
    });

    var width = 960,
        height = 500;

    var force = d3.layout.force()
        .nodes(d3.values(nodes))
        .links(links)
        .size([width, height])
        .linkDistance(100)
        .charge(-300)
        .on("tick", tick)
        .start();

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

    svg.append("svg:defs").selectAll("marker")
        .data(["arrow"])
        .enter().append("svg:marker")
        .attr("id", "arrow")
        .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", "#f0f0f0");

    var link = svg.append("svg:g").selectAll("line")
        .data(force.links())
        .enter().append("svg:line")
        .attr("class", "link")
        .attr("marker-mid", "url(#arrow)");

    var node = svg.append("svg:g").selectAll(".node")
        .data(force.nodes())
        .enter().append("g")
        .attr("class", "node")
        .call(force.drag);

    node.append("circle")
        .attr("r", 8);

    node.append("text")
        .attr("x", -22)
        .text(function(d) {
        return d.name;
    });

    function tick() {
        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;
        });
        link.attr("marker-mid", "url(#arrow)");

        node.attr("transform", function(d) {
            return "translate(" + d.x + "," + d.y + ")";
        });
    }

And here is my jsfiddle

1条回答
地球回转人心会变
2楼-- · 2020-02-14 10:46

From the MDN docu on marker-mid:

The marker-mid defines the arrowhead or polymarker that shall be drawn at every vertex other than the first and last vertex of the given element or basic shape.

So the marker will be inserted at every vertex, but the start and end.

A simple line segment, however, has no other vertices, but its start and end. Thus there are no markers shown in your code.

If you change your marker-mid to, e.g., marker-end, you will see the arrow heads (although right now, they are not that pretty): fiddle.

Another way, would be to change the line-elements to path elements and add a additional vertex in the mid. This, however, would require some more sufficient code.

查看更多
登录 后发表回答