d3.js:将link-label对齐到链接本身

8zzbczxx  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(120)

https://i.stack.imgur.com/yDYD3.png
你好社区!在照片里我想达到的是...这是我目前为止的工作代码(与图片的左半部分相关联):

var diagramElement = this.getElement(); 
    var links = eval(this.getState().string);
    // string = e.g. "[{source: \"Germany\", target: \"Europe\", property: \"is type\", type: \"connection\"}]"
    var width = 800, height = 300;

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

    var force = d3.layout.force()
    .size([width, height])
    .linkDistance(100)
    .charge(-400)
    .on("tick", tick);

    var link;
    var circle;
    var text;
    var nodes = {};
    var linktext;

   svg.append("defs")
    .selectAll("marker").data(["connection", "new"]).enter()
    .append("marker")
    .attr("id", function(d) { return d; })
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 15)
    .attr("refY", 0)
    .attr("markerWidth", 8)
    .attr("markerHeight", 8)
    .attr("orient", "auto")
    .append("svg:path")
    .attr("d", "M0,-5L10,0L0,5");

    this.onStateChange = function() {

        svg.selectAll("g").remove();
        nodes = {};
        links = [];

        links = eval(this.getState().string);
        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});
        });

        force
            .nodes(d3.values(nodes))
            .links(links)
            .on("tick", tick)
            .start();

        link = svg.append("g").selectAll("line.link")
            .data(force.links())
            .enter()
            .append("svg:line")
            .attr("class", function(d) {return "link " + d.type;})
            .attr("marker-end", function(d) {return "url(#" + d.type + ")";});

        circle = svg.append("g").selectAll("circle")
            .data(force.nodes())
            .enter()
            .append("circle")
            .attr("r", 8)
            .call(force.drag);

        text = svg.append("g").selectAll("text")
            .data(force.nodes())
            .enter()
            .append("text")
            .style("font-size","15px")
            .attr("x", 10)
            .attr("y", ".42em")
            .text(function(d) {return d.name;});

            // this is where the linktext is aligned relatively to the links
            // must change something here 
        linktext = svg.append("g").selectAll("text")
            .data(force.links())
            .enter()
            .append("text")
            .style("font-size","15px")
            .attr("dx", 1)
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
            .text(function(d) {return d.type;});

    };

    function tick() {

        circle.attr("cx", function(d) { return d.x = Math.max(12, Math.min(798 - 12, d.x)); })
              .attr("cy", function(d) { return d.y = Math.max(12, Math.min(279 - 12, d.y)); });

        text.attr("transform", transform);

        // linktext position update     
        linktext.attr("transform", function(d) {return "translate(" + (d.source.x + d.target.x) / 2 + "," + (d.source.y + d.target.y) / 2 + ")";});   

        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; });  
    }
    function transform(d) {
        return "translate(" + d.x + "," + d.y + ")";
    }

字符串
所以我已经成功地附加了文本的链接,但现在我如何将位置略高于链接,在链接的方向,如我所附的图片?
我很感激任何帮助

blmhpbnm

blmhpbnm1#

在确定链接的位置后,你也可以像这样应用一些转换:

linkLabels
    .attr('transform', d => {
        // Adding to the transform. Multiple transforms would just get overwritten.
        let transformation = ``

        // The text position should be at the middle of the line
        const x = (d.source.x + d.target.x) / 2
        const y = (d.source.y + d.target.y) / 2
        transformation += `translate(${x}, ${y}) `
        
        // Make sure the text is always upright
        if(d.source.x > d.target.x) {
            transformation += `rotate(180) `
        }
        // Aligning text to the slope.
        // The formula for the tangent of a slope is (y2 - y1) / (x2 - x1) 
        // where (xi, yi) are the coordinates of the line endings
        const angle = Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x)
        transformation += `rotate(${angle * 180/Math.PI}) `

        return transformation
    })

字符串

相关问题