D3 Force -使用动态refX为链接创建标记,以反映不同的节点大小
D3 Force - creating markers for links with dynamic refX to reflect varying node size
我为每个链接创建了一个标记,该标记具有refX = link.target.radius并赋予每个链接不同的id。然后,我用各自的id为每个链接添加了标记-end,以便它根据目标节点半径指定的refX拾取正确的标记。
links = d3.select("svg").selectAll(".link")
.data(force.links())
.enter()
.append("path")
.attr("class", "link")
.attr("stroke", "grey")
.attr("fill", "black")
.attr("stroke-width", 10)
.attr("marker-end", function(d) { return "url(#marker" + force.nodes()[d.target].id + ")"})
defs = d3.select("#svg").append("defs").selectAll(".marker")
.data(force.links())
.enter()
.append("marker")
.attr("class", "marker")
.attr("id", function(d) { return "marker" + force.nodes()[d.target].id })
.attr("viewBox", "0 -5 10 10")
.attr("refX", function(d) { return force.nodes()[d.target].radius})
.attr("refY", 0)
.attr("markerWidth", 13)
.attr("markerHeight", 13)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5 L10,0 L0,5")
.style("stroke", "black")
.style("fill", "black")
.style("opacity", "1");
jsfiddle here - https://jsfiddle.net/6hustc0h/2/
看起来一切都像控制台应该的那样工作-标记正在创建良好,具有不同的id。这些id被正确地附加到链接上,并且标记箭头本身肯定会从链接的末端移到远离目标节点的位置。
但是它们没有正确地置换。refX = 40的标记已正确移动到节点的边缘。refX = 20的标记没有一直移动到节点的末尾。
你的代码有两个问题:
-
将
markerWidth
设置为13将定义标记元素适合的视口宽度。这本身就很好,并将在SVG使用的坐标系统中为标记提供13的宽度。但是,通过在标记上指定viewBox
,您已经为<marker>
元素的内容建立了一个内部坐标系统。在评价refX
时将使用这个内部坐标系:坐标在应用' viewBox '和' preserveAspectRatio '属性后在坐标系中定义。
如果你将
refX
设置为所需的偏移量,则不会考虑将viewPort适应标记宽度所需的缩放。需要考虑13/10的比例因子。 -
当设置偏移量时,你缺少添加标记本身的宽度,即你偏离了10。
根据你的需要,有几种方法可以解决这个问题,只要你保持坐标系统同步。在下面的代码片段中,我将markerWidth
设置为10,这将通过使外部和内部宽度具有相同的大小来处理它。这使您不必进行任何缩放,但也会略微减小SVG中的标记大小。如果你需要的大小正好是13,你将不得不做一些计算,但是。可以将示例中的相关行更改为:
.attr("viewBox", "0 -5 10 10")
.attr("refX", function(d) {
return force.nodes()[d.target].radius + 10; // Add the marker's width
})
.attr("refY", 0)
.attr("markerWidth", 10) // markerWidth equals viewBox width
.attr("markerHeight", 10)
var nodes = [{id:1, "radius": 20, "colour": "black"}, {id:2, "radius":40, "colour":"red"}, {id:3, "radius":30, "colour": "green"}];
var links = [{source: 0, target: 1}, {source: 1, target: 2}, {source: 2, target: 0}];
var svg = d3.select("body").append("svg").attr("width", 500).attr("height", 500).style("border", "1px solid black").attr("id", "svg");
var force = d3.layout.force()
.size([500,500])
.links(links)
.nodes(nodes)
.linkDistance(150)
.on("tick", tick);
var nodes, links, defs;
function render() {
nodes = d3.select("#svg").selectAll(".node")
.data(force.nodes())
.enter()
.append("circle")
.attr("class", "node")
.attr("r", function(d) { return d.radius})
.attr("fill", "none")
.attr("stroke", "black");
links = d3.select("svg").selectAll(".link")
.data(force.links())
.enter()
.append("path")
.attr("class", "link")
.attr("stroke", "grey")
.attr("fill", "black")
.attr("stroke-width", 1)
.attr("marker-end", function(d) { return "url(#marker" + force.nodes()[d.target].id + ")"})
defs = d3.select("#svg").append("defs").selectAll(".marker")
.data(force.links())
.enter()
.append("marker")
.attr("class", "marker")
.attr("id", function(d) { return "marker" + force.nodes()[d.target].id })
.attr("viewBox", "0 -5 10 10")
.attr("refX", function(d) {
return force.nodes()[d.target].radius + 10; // Add the marker's width of 10
})
.attr("refY", 0)
.attr("markerWidth", 10) // markerWidth equals viewBox width
.attr("markerHeight", 10)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5 L10,0 L0,5")
.style("stroke", "black")
.style("fill", "black")
.style("opacity", "1");
};
function tick() {
nodes.attr("cx", function(d) {return d.x})
.attr("cy", function(d) {return d.y});
links.attr("d", function(d) {
var x0 = d.source.x,
y0 = d.source.y,
x1 = d.target.x,
y1 = d.target.y;
return "M" + [x0,y0] + " L" + [x1,y1] + "";
});
};
render()
force.start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
- 节点导出返回一个空对象
- 可以前端maven插件使用节点,npm已经安装
- 在jstree中,如何将指定的节点集中到大型树上
- 节点Js:How to catch a“;没有这样的文件或目录“;读取线模块出错
- 如何从模块链中调用函数.导出到节点中
- 节点是否需要模块传递带有方括号的arg?这是个错误吗
- d3基于用户选择动态更新节点
- 有条件更新d3.js力图中节点的最佳方法
- 如何处理node.js节点mongodb中的连接和查询队列
- 将DOM节点值与字符串Javascript进行比较
- 节点fs.stat名称未定义
- 无法安装节点sass相关性
- 手动将节点添加到JavaScript InfoVis Toolkit Force Directed Graph
- d3-force仅在单击时显示某些链接和节点
- 在d3js Force Layout中向节点添加箭头和文本
- 使用Force Layout从两个不同的csv文件中读取节点和边
- D3 Force -使用动态refX为链接创建标记,以反映不同的节点大小
- 在Force-Layout中用图像标记节点
- 在版本4中动态添加节点到D3 Force布局
- 自定义 force.drag 会在悬停时丢失粘性节点