sud*_*008 6 javascript svg graph d3.js
我有一些不同半径的圆/节点,我必须用箭头末端的路径连接它们.
这是标记的代码:
svg.append("svg:defs").selectAll("marker")
.data(["default"])
.enter().append("svg:marker")
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 5)
.attr("refY", -1.5)
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M1,-5L10,0L0,5");
Run Code Online (Sandbox Code Playgroud)
我已将圆的半径存储在数组中.这是屏幕截图:

箭头实际上是"圈内".如何让箭头位于圆圈表面?
小智 6
这是一个老问题,但如果您希望箭头位于节点的边缘而不是在它们的顶部或下方,这是我的解决方案.我的方法也是绘制连接节点的路径,使得端点位于节点的边缘而不是节点的中心.从Mobile Patent Suits示例(http://bl.ocks.org/mbostock/1153292)开始,我将linkArc方法替换为:
function linkArc(d) {
var sourceX = d.source.x;
var sourceY = d.source.y;
var targetX = d.target.x;
var targetY = d.target.y;
var theta = Math.atan((targetX - sourceX) / (targetY - sourceY));
var phi = Math.atan((targetY - sourceY) / (targetX - sourceX));
var sinTheta = d.source.r * Math.sin(theta);
var cosTheta = d.source.r * Math.cos(theta);
var sinPhi = d.target.r * Math.sin(phi);
var cosPhi = d.target.r * Math.cos(phi);
// Set the position of the link's end point at the source node
// such that it is on the edge closest to the target node
if (d.target.y > d.source.y) {
sourceX = sourceX + sinTheta;
sourceY = sourceY + cosTheta;
}
else {
sourceX = sourceX - sinTheta;
sourceY = sourceY - cosTheta;
}
// Set the position of the link's end point at the target node
// such that it is on the edge closest to the source node
if (d.source.x > d.target.x) {
targetX = targetX + cosPhi;
targetY = targetY + sinPhi;
}
else {
targetX = targetX - cosPhi;
targetY = targetY - sinPhi;
}
// Draw an arc between the two calculated points
var dx = targetX - sourceX,
dy = targetY - sourceY,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + sourceX + "," + sourceY + "A" + dr + "," + dr + " 0 0,1 " + targetX + "," + targetY;
}
Run Code Online (Sandbox Code Playgroud)
请注意,此代码要求"r"或radius属性位于节点数据中.为了将箭头的点放在正确的位置,我更改了refX和refY属性,以便箭头的点位于节点的边缘:
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", 10)
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
Run Code Online (Sandbox Code Playgroud)
这真的很有趣; 我昨天刚刚解决了这个问题.
我所做的是结束节点边缘的路径,而不是中心.我的情况比较复杂,因为我使用Bezier曲线,而不是直线,但这可能对您有所帮助:
svg.append("svg:defs").selectAll("marker")
.data(["default"])
.enter().append("svg:marker")
.attr("id", String)
.attr("viewBox", "0 -3 6 6")
.attr("refX", 5.0)
.attr("refY", 0.0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-2.0L5,0L0,2.0");
links
.attr("fill", "none")
.attr("d", function(d) {
var tightness = -3.0;
if(d.type == "straight")
tightness = 1000;
// Places the control point for the Bezier on the bisection of the
// segment between the source and target points, at a distance
// equal to half the distance between the points.
var dx = d.target.x - d.source.x;
var dy = d.target.y - d.source.y;
var dr = Math.sqrt(dx * dx + dy * dy);
var qx = d.source.x + dx/2.0 - dy/tightness;
var qy = d.source.y + dy/2.0 + dx/tightness;
// Calculates the segment from the control point Q to the target
// to use it as a direction to wich it will move "node_size" back
// from the end point, to finish the edge aprox at the edge of the
// node. Note there will be an angular error due to the segment not
// having the same direction as the curve at that point.
var dqx = d.target.x - qx;
var dqy = d.target.y - qy;
var qr = Math.sqrt(dqx * dqx + dqy * dqy);
var offset = 1.1 * node_size(d.target);
var tx = d.target.x - dqx/qr* offset;
var ty = d.target.y - dqy/qr* offset;
return "M" + d.source.x + "," + d.source.y + "Q"+ qx + "," + qy
+ " " + tx + "," + ty; // to "node_size" pixels before
//+ " " + d.target.x + "," + d.target.y; // til target
});
Run Code Online (Sandbox Code Playgroud)
顺便说说; 你必须为'源'箭头做同样的事情(我只在目标上有它)
| 归档时间: |
|
| 查看次数: |
2322 次 |
| 最近记录: |