Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.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 - Fatal编程技术网

Javascript D3力布局:根据节点半径沿链接移动箭头

Javascript D3力布局:根据节点半径沿链接移动箭头,javascript,svg,d3.js,force-layout,Javascript,Svg,D3.js,Force Layout,在此D3中: 节点具有可变半径。我设法移动节点标签,使它们总是紧挨着圆 但是,如何移动箭头?(你可以看到,对于微软、苹果等公司来说,他们几乎被圆圈所覆盖) 相关问题: 要根据节点半径调整箭头的位置,可以调整路径的端点。更新 我在网上搜索,没有一个答案有效,所以我自己做了: 代码如下: //arrows svg.append("defs").selectAll("marker") .data(["suit", "licensing", "resolved"]) .en

在此
D3
中:

节点具有可变半径。我设法移动节点标签,使它们总是紧挨着圆

但是,如何移动箭头?(你可以看到,对于微软、苹果等公司来说,他们几乎被圆圈所覆盖)

相关问题:


要根据节点半径调整箭头的位置,可以调整路径的端点。更新


我在网上搜索,没有一个答案有效,所以我自己做了:

代码如下:

   //arrows
svg.append("defs").selectAll("marker")
    .data(["suit", "licensing", "resolved"])
    .enter().append("marker")
    .attr("id", function(d) { return d; })
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 9)
    .attr("refY", 0)
    .attr("markerWidth", 10)
    .attr("markerHeight", 10)
    .attr("orient", "auto")
    .append("path")
    .attr("d", "M0,-5L10,0L0,5 L10,0 L0, -5")
    .style("stroke", "#4679BD")
    .style("opacity", "0.6"); 

  //Create all the line svgs but without locations yet
var link = svg.selectAll(".link")
   .data(forceData.links)
   .enter().append("line")
   .attr("class", "link")
   .style("marker-end", "url(#suit)");

//Set up the force layout
var force = d3.layout.force()
    .nodes(forceData.nodes)
    .links(forceData.links)
    .charge(-120)
    .linkDistance(200)
    .size([width, height])
    .on("tick", tick)
    .start();

function tick(){
    link.attr("x1", function (d) { return d.source.x; })
        .attr("y1", function (d) { return d.source.y; })
        .attr("x2", function (d) { 
            return calculateX(d.target.x, d.target.y, d.source.x, d.source.y, d.target.radius); 
        })
        .attr("y2", function (d) { 
            return calculateY(d.target.x, d.target.y, d.source.x, d.source.y, d.target.radius);
        });

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

    d3.select("#forcelayoutGraph").selectAll("text")
        .attr("x", function (d) { return d.x; })
        .attr("y", function (d) { return d.y; });
}
function calculateX(tx, ty, sx, sy, radius){
    if(tx == sx) return tx;                 //if the target x == source x, no need to change the target x.
    var xLength = Math.abs(tx - sx);    //calculate the difference of x
    var yLength = Math.abs(ty - sy);    //calculate the difference of y
    //calculate the ratio using the trigonometric function
    var ratio = radius / Math.sqrt(xLength * xLength + yLength * yLength);
    if(tx > sx)  return tx - xLength * ratio;    //if target x > source x return target x - radius
    if(tx < sx) return  tx + xLength * ratio;    //if target x < source x return target x + radius
}
function calculateY(tx, ty, sx, sy, radius){
    if(ty == sy) return ty;                 //if the target y == source y, no need to change the target y.
    var xLength = Math.abs(tx - sx);    //calculate the difference of x
    var yLength = Math.abs(ty - sy);    //calculate the difference of y
    //calculate the ratio using the trigonometric function
    var ratio = radius / Math.sqrt(xLength * xLength + yLength * yLength);
    if(ty > sy) return ty - yLength * ratio;   //if target y > source y return target x - radius
    if(ty < sy) return ty + yLength * ratio;   //if target y > source y return target x - radius
}
//箭头
svg.append(“defs”).selectAll(“marker”)
.数据([“诉讼”、“许可”、“已解决”])
.enter().append(“标记”)
.attr(“id”,函数(d){return d;})
.attr(“视图框”,“0-5 10”)
.attr(“参考文献”,第9页)
.attr(“参考文献”,0)
.attr(“markerWidth”,10)
.attr(“markerHeight”,10)
.attr(“方向”、“自动”)
.append(“路径”)
.attr(“d”,“M0,-5L10,0L0,5L10,0L0,-5”)
.style(“笔划”,“#4679BD”)
.样式(“不透明度”、“0.6”);
//创建所有直线SVG,但尚未创建位置
var link=svg.selectAll(“.link”)
.data(forceData.links)
.enter().append(“行”)
.attr(“类”、“链接”)
.style(“标记结束”、“url(#suit)”);
//设置部队布局
var-force=d3.layout.force()
.nodes(forceData.nodes)
.links(forceData.links)
。收费(-120)
.linkDistance(200)
.尺寸([宽度、高度])
.on(“滴答”,滴答)
.start();
函数tick(){
attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){
返回calculateX(d.target.x,d.target.y,d.source.x,d.source.y,d.target.radius);
})
.attr(“y2”,函数(d){
返回calculateY(d.target.x,d.target.y,d.source.x,d.source.y,d.target.radius);
});
d3.选择全部(“圆圈”)
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
d3.选择(“强制布局图”)。选择全部(“文本”)
.attr(“x”,函数(d){return d.x;})
.attr(“y”,函数(d){返回d.y;});
}
函数计算器(tx、ty、sx、sy、半径){
if(tx==sx)返回tx;//如果目标x==source x,则无需更改目标x。
var xLength=Math.abs(tx-sx);//计算x的差值
var-yllength=Math.abs(ty-sy);//计算y的差
//使用三角函数计算比率
变压比=半径/数学sqrt(X长度*X长度+Y长度*Y长度);
如果(tx>sx)返回tx-xLength*比率;//如果目标x>源x返回目标x-半径
if(txsy)返回ty-yllength*比值;//if target y>source y返回target x-radius
if(tysource y返回target x-半径
}

通过将参考点(相对于标记绘制到每条路径中的参考点)从0,0移开来偏移箭头。这是通过.attr(“refX”,15)完成的。增加该数字会将箭头移开。请注意,此技术并不完善:首先,它将相同的refX应用于所有标记。由于需要它取决于节点半径,因此必须进行额外的工作创建并为每个圆创建一个标记。其次,箭头移动得越远,其旋转与路径切线的匹配程度就越低。使链接保持直线可以避免此问题。+1它可以工作!我在找你做的算法。这和我以前为了另一个目的做的一样。
   //arrows
svg.append("defs").selectAll("marker")
    .data(["suit", "licensing", "resolved"])
    .enter().append("marker")
    .attr("id", function(d) { return d; })
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 9)
    .attr("refY", 0)
    .attr("markerWidth", 10)
    .attr("markerHeight", 10)
    .attr("orient", "auto")
    .append("path")
    .attr("d", "M0,-5L10,0L0,5 L10,0 L0, -5")
    .style("stroke", "#4679BD")
    .style("opacity", "0.6"); 

  //Create all the line svgs but without locations yet
var link = svg.selectAll(".link")
   .data(forceData.links)
   .enter().append("line")
   .attr("class", "link")
   .style("marker-end", "url(#suit)");

//Set up the force layout
var force = d3.layout.force()
    .nodes(forceData.nodes)
    .links(forceData.links)
    .charge(-120)
    .linkDistance(200)
    .size([width, height])
    .on("tick", tick)
    .start();

function tick(){
    link.attr("x1", function (d) { return d.source.x; })
        .attr("y1", function (d) { return d.source.y; })
        .attr("x2", function (d) { 
            return calculateX(d.target.x, d.target.y, d.source.x, d.source.y, d.target.radius); 
        })
        .attr("y2", function (d) { 
            return calculateY(d.target.x, d.target.y, d.source.x, d.source.y, d.target.radius);
        });

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

    d3.select("#forcelayoutGraph").selectAll("text")
        .attr("x", function (d) { return d.x; })
        .attr("y", function (d) { return d.y; });
}
function calculateX(tx, ty, sx, sy, radius){
    if(tx == sx) return tx;                 //if the target x == source x, no need to change the target x.
    var xLength = Math.abs(tx - sx);    //calculate the difference of x
    var yLength = Math.abs(ty - sy);    //calculate the difference of y
    //calculate the ratio using the trigonometric function
    var ratio = radius / Math.sqrt(xLength * xLength + yLength * yLength);
    if(tx > sx)  return tx - xLength * ratio;    //if target x > source x return target x - radius
    if(tx < sx) return  tx + xLength * ratio;    //if target x < source x return target x + radius
}
function calculateY(tx, ty, sx, sy, radius){
    if(ty == sy) return ty;                 //if the target y == source y, no need to change the target y.
    var xLength = Math.abs(tx - sx);    //calculate the difference of x
    var yLength = Math.abs(ty - sy);    //calculate the difference of y
    //calculate the ratio using the trigonometric function
    var ratio = radius / Math.sqrt(xLength * xLength + yLength * yLength);
    if(ty > sy) return ty - yLength * ratio;   //if target y > source y return target x - radius
    if(ty < sy) return ty + yLength * ratio;   //if target y > source y return target x - radius
}