【问题标题】:How to achieve force layout network in Konva?如何在 Konva 中实现力布局网络?
【发布时间】:2019-10-05 16:38:36
【问题描述】:

如何在Konva.js中实现强制布局网络?

下面是例子:

Example

【问题讨论】:

    标签: javascript force-layout konvajs


    【解决方案1】:

    Konva 没有内置物理引擎。所以你必须使用模拟所需物理的外部代码。例如,您可以在这种情况下使用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

    【讨论】:

    • 当我移动一个节点并按住它时,它会稍微摇晃/摇晃,过一会儿它会自行释放?
    • @MartinS 可能需要一些修复才能更好地集成 d3 引擎。
    • 好的,具体可能是什么问题?
    • @MartinS Konva 拖放到 d3 力引擎中可能需要更多反馈。就像 dragstart 告诉 d3 节点不应该被我的力量移动。
    最近更新 更多