【问题标题】:D3.js static force layout not working with path?D3.js 静态力布局不适用于路径?
【发布时间】:2017-11-12 14:53:54
【问题描述】:

我正在尝试更改此示例 https://bl.ocks.org/mbostock/1667139 以使用路径而不是行,但它不起作用。 我尝试像这样使用自己的刻度功能:

function tick() {
            link.attr("d", function(d) {
            var x1 = d.source.x,
                y1 = d.source.y,
                x2 = d.target.x,
                y2 = d.target.y,
                dx = x2 - x1,
                dy = y2 - y1,
                dr = Math.sqrt(dx * dx + dy * dy),

                // z uzla do ineho uzla
                drx = dr,
                dry = dr,
                xRotation = 0,
                largeArc = 0,
                sweep = 1;

            //do sameho seba
            if ( x1 === x2 && y1 === y2 ) {
                xRotation = -45;
                largeArc = 1;
                drx = 30;
                dry = 30;
                x2 = x2 + 1;
                y2 = y2 + 1;
            }

            return "M" + x1 + "," + y1 + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + x2 + "," + y2;
        });     
}

我不知道,如果我遗漏了某些东西或静态力布局就无法使用路径。 路径正常工作的强制布局

【问题讨论】:

    标签: javascript d3.js force-layout


    【解决方案1】:

    来自docs(我的粗体字):

    simulation.tick()

    将当前 alpha 增加 (alphaTarget - alpha) × alphaDecay; 然后调用每个注册的力,传递新的阿尔法;然后 按速度 × velocityDecay 递减每个节点的速度;最后 以速度递增每个节点的位置。

    此方法不分派事件;事件仅由 模拟自动启动时的内部计时器 创建或通过调用simulation.restart。自然刻度数 模拟开始时是 ⌈log(alphaMin) / log(1 - alphaDecay)⌉;默认情况下,这是 300。

    这个方法可以和simulation.stop结合使用来计算 静态力布局。对于大图,静态布局应该是 在网络工作者中计算以避免冻结用户界面。

    由于它不分派事件,因此您的 tick 函数永远不会被调用或使用。相反,只需替换该行并设置一次路径:

    <!DOCTYPE html>
    <svg width="960" height="500"></svg>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script>
      var svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height"),
        g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
      var n = 100,
        nodes = d3.range(n).map(function(i) {
          return {
            index: i
          };
        }),
        links = d3.range(n).map(function(i) {
          return {
            source: i,
            target: (i + 3) % n
          };
        });
    
      var simulation = d3.forceSimulation(nodes)
        .force("charge", d3.forceManyBody().strength(-80))
        .force("link", d3.forceLink(links).distance(20).strength(1).iterations(10))
        .force("x", d3.forceX())
        .force("y", d3.forceY())
        .stop();
    
      var loading = svg.append("text")
        .attr("dy", "0.35em")
        .attr("text-anchor", "middle")
        .attr("font-family", "sans-serif")
        .attr("font-size", 10)
        .text("Simulating. One moment please…");
    
      // Use a timeout to allow the rest of the page to load first.
      d3.timeout(function() {
        loading.remove();
    
        // See https://github.com/d3/d3-force/blob/master/README.md#simulation_tick
        for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
          simulation.tick();
        }
    
        g.append("g")
          .attr("stroke", "#000")
          .attr("stroke-width", 1.5)
          .selectAll("line")
          .data(links)
          .enter().append("path")
          .attr("d", function(d) {
            var x1 = d.source.x,
              y1 = d.source.y,
              x2 = d.target.x,
              y2 = d.target.y,
              dx = x2 - x1,
              dy = y2 - y1,
              dr = Math.sqrt(dx * dx + dy * dy),
    
              // z uzla do ineho uzla
              drx = dr,
              dry = dr,
              xRotation = 0,
              largeArc = 0,
              sweep = 1;
    
            //do sameho seba
            if (x1 === x2 && y1 === y2) {
              xRotation = -45;
              largeArc = 1;
              drx = 30;
              dry = 30;
              x2 = x2 + 1;
              y2 = y2 + 1;
            }
    
            return "M" + x1 + "," + y1 + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + x2 + "," + y2;
          });
    
        g.append("g")
          .attr("stroke", "#fff")
          .attr("stroke-width", 1.5)
          .selectAll("circle")
          .data(nodes)
          .enter().append("circle")
          .attr("cx", function(d) {
            return d.x;
          })
          .attr("cy", function(d) {
            return d.y;
          })
          .attr("r", 4.5);
    
    
      });
    </script>

    对 cme​​ts 的回应:

    要将圆圈和文本附加为“节点”,我会创建一个g,定位它,然后将圆圈和文本放入其中:

      var g = node
        .selectAll(".node")
        .data(nodes)
        .enter()
        .append("g")
        .attr("transform", function(d){
          return "translate(" + d.x + "," + d.y + ")";
        });
    
      g.append("circle")
        .attr("class", "node")
        .attr("stroke", "#fff")
        .attr("r", 28);
    
      g.append("text")
        .text("test");
    

    【讨论】:

    • 真的谢谢,我能再问你一件事吗?如何将文字添加到每个圈子?非静态力布局只需创建 var circle.append("g") 然后 append("circle") 然后 append("text") 用于添加文本,但在这里不起作用。我的尝试在这里jsfiddle.net/f7e20crm。当是圆形和文本元素时,该文本是单独的元素而不是 g 元素的一部分
    • @Martin,请参阅您问题的更新答案。并更新了小提琴here
    猜你喜欢
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 2014-12-15
    • 2019-09-30
    • 2012-10-28
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多