差异力与中心之间的转换'在d3 v4

时间:2016-12-04 20:27:40

标签: javascript d3.js window-resize

当我调整窗口大小时,我会开始调整大小'将要做的事件:

var width = +container.clientWidth;
var height = +container.clientHeight;
simulation.force('center', d3.forceCenter(width / 2, height / 2));
simulation.alphaTarget(0.3).restart();

将我的节点链接图置于画布中间。 这样做很好,但是我没有向中心过渡,而是立即跳转。

我希望有一个动画,如本例所示:https://bl.ocks.org/mbostock/raw/3355967/

然而,在d3 v4中,我不知道如何实现这种转变。我是否必须使用不同的力量,或者我是否可以强制执行过渡'?我必须在哪里声明它?

示例:https://jsfiddle.net/n4m1r8nb/157/(它位于开头的左上角,当您调整大小时,它会“跳到中心”#);

似乎已经在d3 v3中通过以下方式完成:

force.size([width, height]).resume();

但是,此方法在v4中不再可用,并替换为forceCenter(或forceX,forceY)。

2 个答案:

答案 0 :(得分:3)

您可以通过设置transition

来实现



var nodes = [{
  "id": 1,
  "name": "server 1"
}, {
  "id": 2,
  "name": "server 2"
}, {
  "id": 3,
  "name": "server 3"
}, {
  "id": 4,
  "name": "server 4"
}, {
  "id": 5,
  "name": "server 5"
}, {
  "id": 6,
  "name": "server 6"
}, {
  "id": 7,
  "name": "server 7"
}, {
  "id": 8,
  "name": "server 8"
}, {
  "id": 9,
  "name": "server 9"
}]

var links = [{
  source: 1,
  target: 2
}, {
  source: 1,
  target: 3
}, {
  source: 1,
  target: 4
}, {
  source: 2,
  target: 5
}, {
  source: 2,
  target: 6
}, {
  source: 3,
  target: 7
}, {
  source: 5,
  target: 8
}, {
  source: 6,
  target: 9
}, ]

var index = 10;
var svg = d3.select("svg"),
  width = document.getElementById('container').clientWidth,
  height = document.getElementById('container').clientHeight,
  node,
  link;

d3.select(window).on('resize', function() {
  var w = document.getElementById('container').clientWidth;
  var h = document.getElementById('container').clientHeight;

  d3.select({}).transition().delay(500)
    .tween("center.move", function() {
        var i = d3.interpolateArray([width/2, height/2],[w/2,h/2]);
        width = w; height = h;
      return function(t) {
      	var c = i(t);
        simulation.force('center', d3.forceCenter(c[0], c[1]));
        simulation.alphaTarget(0.3).restart();
      };
    });  
});


var simulation = d3.forceSimulation()
  .force("link", d3.forceLink().id(function(d) {
    return d.id;
  }))
  .force("charge", d3.forceManyBody())
  .force("center", d3.forceCenter(width / 2, height / 2));

update();

function update() {
  link = svg.selectAll(".link")
    .data(links, function(d) {
      return d.target.id;
    })

  link = link.enter()
    .append("line")
    .attr("class", "link");

  node = svg.selectAll(".node")
    .data(nodes, function(d) {
      return d.id;
    })

  node = node.enter()
    .append("g")
    .attr("class", "node");

  node.append("circle")
    .attr("r", 2.5)

  simulation
    .nodes(nodes)
    .on("tick", ticked);

  simulation.force("link")
    .links(links);
}

function ticked() {
  link
    .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;
    });

  node
    .attr("transform", function(d) {
      return "translate(" + d.x + ", " + d.y + ")";
    });
}

.link {
  stroke: #aaa;
}

svg {
  width: 100%;
  height: 100%;
}

#container {
  width: 100%;
  height: 100%;
}

.node {
  pointer-events: all;
  stroke: none;
  stroke-width: 40px;
}

<script src="http://d3js.org/d3.v4.js"></script>
<div id="container">
  <svg></svg>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

要立即过渡(比补间更容易的替代方法),只需移除指示中心的当前力,然后创建一个新的力即可:

例如

d3.select(window).on('resize', function() {
    let w = document.getElementById('container').clientWidth;
    let  h = document.getElementById('container').clientHeight;

    simulation.force("center", null)
        simulation.force('center', d3.forceCenter(w / 2, h / 2));
});

如果您正在寻找平滑过渡(如补间),只需使用.force('x', ...).force('y', ...)而不是上面的.force('center', ...)来使节点居中。