Tôi tìm kiếm trên mạng, không ai trong số các câu trả lời làm việc , vì vậy tôi làm của riêng tôi:
đây là mã:
//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
}
thực ra, tôi không thể nhìn thấy, mũi tên thực sự là "bên trong" vòng tròn. – Oswald
Làm cho đường dẫn bắt đầu và kết thúc tại bán kính vòng tròn thay vì ở giữa. Một số lượng giác sẽ được yêu cầu. –
Tôi có thể sai, nhưng đường dẫn cho các liên kết tách biệt với các điểm đánh dấu tạo nên các mũi tên. '.attr (" refX ", 5)' đặt độ lệch của mũi tên từ giữa vòng tròn. Trong khi nó được chỉ định là bù đắp 'X', bởi vì đối tượng đang quay, nó không tương ứng với trục x (trái và phải) của màn hình. Điều này cũng đúng với dòng '.attr (" refY ", -1.5)'. Khi tôi cố gắng áp dụng một hàm để giải quyết nó, tôi đã thất bại thảm hại. Tôi có thể bù đắp các mũi tên, nhưng không nhất quán với khoảng cách chính xác. – d3noob