缩放 D3 力布局链接标记上的箭头
Scaling an arrowhead on a D3 force layout link marker
我在 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");
问题
这个jsFiddle演示了所讨论的问题。标记 def 的值与它所附加到的元素的斯托克宽度(在本例中为链接线)有关。请参阅标记单位规格。通过将strokeWidth
用于markerUnits
属性,不同大小箭头的坐标将略有不同。简而言之,一种尺寸箭头的适当值不会正确转换为其他尺寸。
解决方案1:多个标记
如评论中所述,一种解决方案是为所需的每个strokeWidth
创建一个不同的标记。只有当您预先知道需要什么尺寸时,这才有效。
解决方案 2:修改线条
另一种选择是修改线的终点。与其允许线终止在节点的中心,不如将其终止在节点的外边缘。这个jsFiddle演示了这一点。这减轻了移动箭头的需要,因为我们现在可以在行尾绘制它。
此解决方案涉及一些数学运算,以确定line
的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
可能太大了。尝试将其设置为 1 左右。
相关文章:
- 在链接d3强制布局中添加和删除类
- 如何在d3力布局中使直线而不是曲线
- 具有树状布局,如何更改X轴以使用D3中的时间刻度
- d3.js绘制具有固定布局的网络
- 可以't去除D3'的放射状树状布局
- 如何使d3.js树布局按字母顺序对节点进行排序
- D3.js强制布局带有外部数据的图形空白
- d3.js:在强制布局中使用缩放时,将禁用拖动
- 是否有类似强制布局但支持单击事件的 D3 布局引擎
- D3 筛选返回函数值强制布局
- 如何在 D3 中使力布局图.js响应屏幕/浏览器大小
- d3.js - 强制布局和节点位置
- D3 力导向布局的基础知识
- 如何在D3中获得可缩放Icicle布局中文本标签的旋转
- d3.js力布局图:如何从头开始构建nodes对象
- 如何使用 D3 布局非树层次结构
- 我可以把一个d3布局放在另一个上面吗
- 动态改变Javascript D3布局模拟
- 我应该使用哪个D3布局来显示关系
- D3 布局树未呈现