Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 缩放D3强制布局链接标记上的箭头_Javascript_Svg_D3.js_Force Layout_Markers - Fatal编程技术网

Javascript 缩放D3强制布局链接标记上的箭头

Javascript 缩放D3强制布局链接标记上的箭头,javascript,svg,d3.js,force-layout,markers,Javascript,Svg,D3.js,Force Layout,Markers,我在d3力定向图中有以下代码,我试图根据一个值(1-3)改变链接及其相关箭头的大小。笔划权重会随该值而变化,但箭头不会保持在正确的位置。当冲程重量从1变为3时,它倾向于从末端向后移动。如何在更改笔划值时保持箭头(标记)正确对齐?非常感谢 var link = vis.selectAll("line.link") .data(json.links) .enter().append("svg:line") .attr("class", "link")

我在d3力定向图中有以下代码,我试图根据一个值(1-3)改变链接及其相关箭头的大小。笔划权重会随该值而变化,但箭头不会保持在正确的位置。当冲程重量从1变为3时,它倾向于从末端向后移动。如何在更改笔划值时保持箭头(标记)正确对齐?非常感谢

      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(#arrowGray)")
      .on("click", function(d) {
            link.style("stroke","#dddddd");
            node.style("stroke","#FFFFFF");
            d3.select(this).style("stroke","red");
            link.attr("marker-end", null);
            link.attr("marker-end", "url(#arrowGray)");
            d3.select(this).attr("marker-end", null);
            d3.select(this).attr("marker-end", "url(#arrowRed)");
            clickLink(d);
            });

    defs.append("svg:marker")
            .attr("id", "arrowGray")
            .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");

您的
refX
可能太大。尝试将其设置为1左右。

问题出在哪里 这说明了问题所在。标记def的值与它所附着的图元(本例中为连接线)的斯托克宽度有关。看。通过对
markerUnits
属性使用
strokeWidth
,不同大小箭头的坐标将略有不同。简而言之,一个尺寸箭头的适当值将无法正确转换为其他尺寸

解决方案1:多个标记 如评论中所述,一种解决方案是为所需的每个
strokeWidth
创建不同的标记。只有当您事先知道需要什么尺寸时,这才有效

解决方案2:修改行 另一个选项是修改直线的端点。不允许线在节点的中心终止,而是在节点的外边缘终止。这说明了这一点。这减轻了移动箭头的需要,因为我们现在可以在线条的末尾绘制箭头

此解决方案涉及一些数学运算,以确定
x2
y2
值应该是什么。因此,对于具有大量边的系统来说,它可能并不理想

var nodeRadius = 10;
var lineX2 = function (d) {
    var length = Math.sqrt(Math.pow(d.target.y - d.source.y, 2) + Math.pow(d.target.x - d.source.x, 2));
    var scale = (length - nodeRadius) / length;
    var offset = (d.target.x - d.source.x) - (d.target.x - d.source.x) * scale;
    return d.target.x - offset;
};
var lineY2 = function (d) {
    var length = Math.sqrt(Math.pow(d.target.y - d.source.y, 2) + Math.pow(d.target.x - d.source.x, 2));
    var scale = (length - nodeRadius) / length;
    var offset = (d.target.y - d.source.y) - (d.target.y - d.source.y) * scale;
    return d.target.y - offset;
};

var link = svg.selectAll("line.link")
    .data(graph.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", lineX2)
    .attr("y2", lineY2)
    .attr("marker-end", "url(#arrowGray)")
    .on("click", function (d) {
        link.style("stroke", "#dddddd");
        node.style("stroke", "#FFFFFF");
        d3.select(this).style("stroke", "red");
        link.attr("marker-end", null);
        link.attr("marker-end", "url(#arrowGray)");
        d3.select(this).attr("marker-end", null);
        d3.select(this).attr("marker-end", "url(#arrowRed)");
    });

var defs = svg.append('defs');
defs.append("svg:marker")
    .attr("id", "arrowGray")
    .attr("viewBox", "0 0 10 10")
    .attr("refX", "10")
    .attr("refY", "5")
    .attr("markerUnits", "strokeWidth")
    .attr("markerWidth", "10")
    .attr("markerHeight", "5")
    .attr("orient", "auto")
    .append("svg:path")
    .attr("d", "M 0 0 L 10 5 L 0 10 z")
    .attr("fill", "#000");

var node = svg.selectAll(".node")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", nodeRadius)
    .style("fill", function (d) {
        return color(d.group);
    })
    .call(force.drag);

node.append("title")
    .text(function (d) {
        return d.name;
    });

force.on("tick", function () {
    link.attr("x1", function (d) {
        return d.source.x;
    })
    .attr("y1", function (d) {
        return d.source.y;
    })
    .attr("x2", lineX2)
    .attr("y2", lineY2)

    node.attr("cx", function (d) {
        return d.x;
    })
    .attr("cy", function (d) {
        return d.y;
    });
});

这是缩放标记的正确方法,因此如果这不适用于您,您可能必须为不同的大小定义不同的标记。如果不设置
refX
/
refY
,而是相应地设置
d
属性,则可能会获得更大的成功。您能给我们一个完整的工作示例吗?这并不能回答这个问题。若要评论或要求作者澄清,请在其帖子下方留下评论。不,@azurefrog,这是对问题的回答。