带有力导向图的鱼眼效应:直到图稳定后才生效

问题描述

我正在创建一个具有鱼眼效果的图形,用户在其光标下有一个永久缩放,并且可以四处移动图形节点。

Here's what I have: (ObservableHQ)

以片段形式:

d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/5916d145c8c048a6e3086915a6be464467391c62/miserables.json").then(draw);
  
function draw(data) {
  
  const fisheye = fisheyeO.circular()
  .radius(100)
  .distortion(5);
  
  const height = 400;
  const width = 500;
  
  data.nodes.forEach(d=>{d.fisheye={x:0,y:0,z:0}})

  const simulation = d3.forceSimulation(data.nodes)
      .alphaDecay(0.0125)
      .alphaMin(0.01)
  .force("link",d3.forceLink(data.links).id(d => d.id))
  .force("charge",d3.forceManyBody())
  .force("x",d3.forceX(width/2))
  .force("y",d3.forceY(height/2));

  const svg = d3.select("body").append("svg")
  .attr("viewBox",[0,width,height])

  const link = svg.append("g")
  .attr("stroke","#999")
  .attr("stroke-opacity",0.6)
  .selectAll("line")
  .data(data.links)
  .join("line")
  .attr("stroke-width",2);
  
  const node = svg.append("g")
  .attr("stroke","#fff")
  .attr("stroke-width",1.5)
  .selectAll("circle")
  .data(data.nodes)
  .join("circle")
  .attr("r",5)
  .attr("fill","black")


  svg.on("mousemove",function() {
    fisheye.focus(d3.mouse(this));

    node.each(function(d) { d.fisheye = fisheye(d); })
      .attr("cx",function(d) { return d.fisheye.x; })
      .attr("cy",function(d) { return d.fisheye.y; })
      .attr("r",function(d) { return d.fisheye.z * 4.5; });

    link.attr("x1",function(d) { return d.source.fisheye.x; })
      .attr("y1",function(d) { return d.source.fisheye.y; })
      .attr("x2",function(d) { return d.target.fisheye.x; })
      .attr("y2",function(d) { return d.target.fisheye.y; });
  })

  simulation.on("tick",() => {
    link
      .attr("x1",d => d.source.x)
      .attr("y1",d => d.source.y)
      .attr("x2",d => d.target.x)
      .attr("y2",d => d.target.y);

    node
      .attr("cx",d => d.x)
      .attr("cy",d => d.y);
  });

}


const fisheye0 = fisheyeO = {
    circular: () => {
      var radius = 200,distortion = 2,k0,k1,focus = [0,0];

      function fisheye(d) {
        var dx = d.x - focus[0],dy = d.y - focus[1],dd = Math.sqrt(dx * dx + dy * dy);
        if (!dd || dd >= radius) return {x: d.x,y: d.y,z: dd >= radius ? 1 : 10};
        var k = k0 * (1 - Math.exp(-dd * k1)) / dd * .75 + .25;
        return {x: focus[0] + dx * k,y: focus[1] + dy * k,z: Math.min(k,10)};
      }

      function rescale() {
        k0 = Math.exp(distortion);
        k0 = k0 / (k0 - 1) * radius;
        k1 = distortion / radius;
        return fisheye;
      }

      fisheye.radius = function(_) {
        if (!arguments.length) return radius;
        radius = +_;
        return rescale();
      };

      fisheye.distortion = function(_) {
        if (!arguments.length) return distortion;
        distortion = +_;
        return rescale();
      };

      fisheye.focus = function(_) {
        if (!arguments.length) return focus;
        focus = _;
        return fisheye;
      };

      return rescale();
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js"></script>

我使用了 Bostock 的鱼眼效果,只要图形是静态的,它就可以正常工作。但是,如果力模拟正在运行,则不起作用,从而产生以下效果:

enter image description here

我尝试将鱼眼效果重构为一种力,并直接在力模拟中使用它,如下所示:

function forceFisheye(fisheye) {
  let nodes;

  function force() {
    let i;
    let n = nodes.length;
    let node;

    for (i = 0; i < n; ++i) {
      node = nodes[i];
      let { x,y,z } = fisheye(node);
      node.x = x;
      node.y = y;
      node.z = z;
    }
  }

  force.initialize = function (_) {
    nodes = _;
  };

  return force;
}

let fisheye = fisheye();

// ...
d3.forceSimulation()
    .force("fisheye",forceFisheye(fisheye));

但是这会产生奇怪的结果,反而让节点从我的光标处跑开。

如何使用具有鱼眼效果的力导向图?

感谢您的宝贵时间!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)