Вопрос:

D3 v4 force layout disable animation on drag

javascript d3.js

890 просмотра

3 ответа

105 Репутация автора

How can i disable the animation while dragging the current node in the force simulation in the d3 version 4

Below is the code which is used for drag the node

var node = svg.selectAll(".node")
            .data(json.nodes)
            .enter().append("g")
            .attr("class", "node")
            .call(d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended));

      function dragstarted(d) {
        if (!d3.event.active) force.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
    }

    function dragged(d) {
        d.fx = d3.event.x;
        d.fy = d3.event.y;
    }

    function dragended(d) {
        if (!d3.event.active) force.alphaTarget(0.3);
        // d.fx = null;
        //d.fy = null;
    } 

When i tried to stop the force while in dragged method it doesn't work out. Please suggest me the best way to stop the animation

Please check this fiddle

Автор: fekky Dev Источник Размещён: 02.01.2018 10:29

Ответы (3)


0 плюса

188 Репутация автора

Взгляните на этот пример: http://bl.ocks.org/norrs/2883411, поскольку он, кажется, выполняет то, что вам нужно.

Как указано в примере и связанном с этим вопросе SO ( силовой ориентированный граф D3 с поддержкой перетаскивания, позволяющий фиксировать положение выбранного узла при удалении ), вам, вероятно, будет лучше создать и использовать собственный прослушиватель перетаскивания для достижения этого конкретного поведения.

Автор: Autio Размещён: 02.01.2018 12:07

1 плюс

72362 Репутация автора

Решение

It's not exactly clear what you mean by "disable the animation". I suppose that you're talking about the movement of the other nodes... well, that's quite the expected behaviour, since you're reheating the simulation.

A possible solution is setting the fx and fy property of all nodes when the simulation ends:

simulation.on("end", function() {
    node.each(function(d) {
        d.fx = d.x;
        d.fy = d.y;
    })
})

Вот ваш код с этим изменением. Дождитесь окончания симуляции (примерно 5 секунд) и перетащите узлы:

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 = +svg.attr("width"),
  height = +svg.attr("height"),
  node,
  link;

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")
    .on("click", click)
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));

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

  node.append("title")
    .text(function(d) {
      return d.id;
    });

  node.append("text")
    .attr("dy", 3)
    .text(function(d) {
      return d.name;
    });

  simulation
    .nodes(nodes)
    .on("tick", ticked)
    .on("end", function() {
      node.each(function(d) {
        d.fx = d.x;
        d.fy = d.y;
      })
    })

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

function click(d) {
  nodes.push({
    id: index,
    name: "server " + index
  });
  links.push({
    source: d.id,
    target: index
  });
  index++;
  update();
}

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 + ")";
    });
}

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart()
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
}
.link {
  stroke: #aaa;
}

.node {
  pointer-events: all;
  stroke: none;
  stroke-width: 40px;
  cursor: pointer;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="600" height="400"></svg>

Автор: Gerardo Furtado Размещён: 02.01.2018 12:08

0 плюса

18 Репутация автора

Это на самом деле очень просто. Просто не определяйте:

.call(d3.drag().on("start", drag_start)
                 .on("drag", drag_drag)
                 .on("end", drag_end))

Это то, что управляет частью анимации, и все же вы обнаружите проблему в поздней загрузке вашего графика из-за огромных данных или чего-то еще, тогда я предлагаю добавить свойство с именем .alphaDecay (0.9), эта конкретная вещь уменьшит длину ссылки, таким образом уменьшая вашу время загрузки графика.

Автор: Priyanka Gupta Размещён: 15.05.2019 05:25
Вопросы из категории :
32x32