Как добиться форс-макета сети в Конве? - PullRequest
0 голосов
/ 18 мая 2019

Как добиться принудительного размещения сети в Konva.js?

Ниже приведен пример:

Пример

1 Ответ

1 голос
/ 19 мая 2019

Конва не имеет встроенных физических движков. Таким образом, вы должны использовать внешний код, который имитирует необходимую физику. Например, вы можете использовать d3 для этого случая.

var w = window.innerWidth;
var h = window.innerHeight;

var dataset = {
  nodes:[
    {name:"Adam"},
    {name:"Bob"},
    {name:"Carrie"},
    {name:"Donovan"},
    {name:"Edward"},
    {name:"Felicity"},
    {name:"George"},
    {name:"Hannah"},
    {name:"Iris"},
    {name:"Jerry"}
  ],
  edges:[
    {source: 0, target: 1},
    {source: 0, target: 2},
    {source: 0, target: 3},
    {source: 0, target: 4},
    {source: 1, target: 5},
    {source: 2, target: 5},
    {source: 2, target: 5},
    {source: 3, target: 4},
    {source: 5, target: 8},
    {source: 5, target: 9},
    {source: 6, target: 7},
    {source: 7, target: 8},
    {source: 8, target: 9},

  ]
};

var force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w, h])
.linkDistance([100])
.charge([-150])
.start();





const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight
});

const layer = new Konva.Layer();
stage.add(layer);


dataset.edges.forEach((edge, i) => {
  const line = new Konva.Line({
    points: [],
    stroke: 'black',
    name: 'edge-' + i
  });
  layer.add(line);
})

dataset.nodes.forEach((n, i) => {
  const circle = new Konva.Circle({
    radius: 30,
    fill: Konva.Util.getRandomColor(),
    name: 'node-' + i,
    draggable: true
  });
  circle.on('dragmove', () => {
    n.x = circle.x(),
    n.y = circle.y();
  })
  circle.on('dragmove', () => {
    force.resume();
  })
  layer.add(circle);
})



force.on("tick", function(){
  dataset.nodes.forEach((node, i) => {
    const circle = layer.findOne('.node-' + i);
    circle.x(node.x);
    circle.y(node.y);
  });
  dataset.edges.forEach((edge, i) => {
    const { target, source } = edge;
    const line = layer.findOne('.edge-' + i);
    line.points([target.x, target.y, source.x, source.y]);
  });
  layer.draw();
});

Демо: https://jsbin.com/kupifekefo/3/edit?js,output

...