D3强制-为具有动态refX的链接创建标记以反映变化的节点大小

hwilson1

我为具有refX = link.target.radius的每个链接创建了一个标记,并为每个链接指定了不同的ID。然后,我将marker-end添加到具有各自ID的每个链接中,以便它使用根据目标节点半径指定的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 - https://jsfiddle.net/6hustc0h/2/

看起来一切正常,都应该在控制台上进行-标记创建得很好,使用了不同的ID。这些ID正确地附加到链接上,并且标记箭头本身肯定从链接的末端移回,并远离目标节点。

但是,它们无法正确移动。refX = 40的标记已正确移动到节点的边缘。refX = 20的标记尚未完全移动到节点的末端。

高积云

您的代码有两个问题:

  1. 设置markerWidth13将定义标记元素适合的视口的宽度。这本身很好,并且会在SVG使用的坐标系中使标记的宽度为13但是,通过viewBox在标记上指定a ,可以为<marker>元素的内容建立内部坐标系在评估时将使用此内部坐标系refX

    应用'viewBox''preserveAspectRatio'属性后,在坐标系中定义坐标

    如果将其设置refX为所需的偏移量,则不会考虑将viewPort适应标记宽度所需的缩放比例。比例因子为13/10

  2. 设置偏移量时,您缺少添加标记本身的宽度的方法,即,偏移量为10

根据您的需要,有几种解决方法,只要您使坐标系保持同步即可。在下面的代码段中,我将设置markerWidth10,通过使外部和内部宽度都具有相同的大小来处理它。这使您无需进行任何缩放,但也会略微减小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>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

d3 强制链接未连接

来自分类Dev

d3在节点中强制布局链接位置

来自分类Dev

D3强制布局:如何设置每个节点的大小?

来自分类Dev

d3强制使用节点组进行布局

来自分类Dev

D3强制布局节点属性未正确更新

来自分类Dev

如何替换d3强制布局中的节点?

来自分类Dev

d3以可预测的顺序强制布局节点

来自分类Dev

d3强制添加和删除节点

来自分类Dev

将节点放置在d3强制布局的屏幕中央

来自分类Dev

D3强制布局,其中较大的节点聚集在中心

来自分类Dev

无法从D3强制箭头图形中删除链接

来自分类Dev

更改d3强制布局链接样式以匹配d3树外观

来自分类Dev

d3强制有向图删除文本光标

来自分类Dev

d3强制有向图不选择文本

来自分类Dev

D3强制有向图ajax更新

来自分类Dev

D3:具有固定Y范围的强制布局-减少链接重叠

来自分类Dev

D3强制布局-如何实现节点的3D外观?

来自分类Dev

D3强制布局应在单击节点时添加节点和链接

来自分类Dev

D3强制布局:链接和节点--- z-index(?)

来自分类Dev

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

来自分类Dev

D3强制布局-按名称而不是索引链接节点

来自分类Dev

更新位置后,D3强制链接未与节点连接

来自分类Dev

D3强制布局:链接和节点--- z-index(?)

来自分类Dev

D3 js强制布局:使用链接参数设置节点半径

来自分类Dev

D3强制定向布局+所有节点到原始位置

来自分类Dev

如何仅将新节点添加到d3强制有向图?

来自分类Dev

D3强制布局中的一个节点上有两个标签

来自分类Dev

在d3强制定向网络图中更新带有标签的节点和链接未正确删除节点

来自分类Dev

在D3强制布局中,在根节点周围均匀地隔开节点

Related 相关文章

热门标签

归档