我们可以为循环边缘类型或子父边缘选择另一种边缘形式吗?

Can we choose another edge form for loop edge type or child-parent edge?

示例 1:

elements: [{
      data: {
        id: 'a'
      }
    },
    {
      data: {
        id: 'b',
        parent: 'a'
      }
    },
    {
      data: {
        id: 'ab',
        source: 'b',
        target: 'a'
      }
    }
  ],
  style: [{
    selector: 'edge',
    css: {
      'curve-style': 'bezier',
      'target-arrow-shape': 'triangle'
    }
  }]

我正在尝试绘制从节点到其父节点的边。 我希望从节点到外部框架有一条直线,如下所示:

但是我得到了这样的曲线:

示例 2:

如果我试图用相同的源和目标制作一条边,它的形式总是一条曲线(就像边类型演示中的循环边类型)。

即使我选择这样的曲线风格:

cy.add([{
    data: {
        "source": guid,
        "target": guid,
    },
    style: {
        "curve-style": "bezier",
        "source-endpoint": '0% 0%',
        "target-endpoint": '0% -80%'
    },
}])

我得到这样的曲线:

同样适用于直线曲线样式。

如何为循环绘制另一种边缘形式?

不确定是否可以不分叉 cytoscape.js,但我可能是错的。

https://codepen.io/Raven0us/pen/yLYZbJx

这里有一个解决方法,使用永远不会显示的幽灵节点。

cy.$('edge.with-compound').forEach((edge, i) => {
    // parent node is edge source
    let position = calculateGhostNodePosition(edge.source());

    // ghost node id needs to keep a reference to the node that was used to calculate its position
    let ghostNodeId = `ghost-${edge.source().id}`;
    cy.add({
        group: 'nodes',
        data: {
            id: ghostNodeId
        },
        position: {
            x: position.x,
            y: position.y
        },
        classes: ['ghost-node']
    });

    cy.add({
        group: 'edges',
        data: {
            id: `${ghostNodeId}-edge`,
            source: edge.data('target'),
            target: ghostNodeId,
            classes: ['ghost-node-connector']
        }
    })
})

cy.$('node[parent]').on('position', e => {
    let node = e.target;
    let targetGhostNode = cy.$(`node[id="ghost-${node.id}"]`);

    let position = calculateGhostNodePosition(node);

    targetGhostNode.position({
        x: position.x,
        y: position.y
    })
})

/**
 *
 * @param sourceNode
 * @returns {{x: number | SVGAnimatedLength, y: *}}
 */
function calculateGhostNodePosition(sourceNode) {
    let boundingBox = sourceNode.boundingBox();

    // you need to actually calculate these and take node size in account
    let x = boundingBox.x1;
    let y = boundingBox.y1 + ((boundingBox.y2 - boundingBox.y1) / 2) + 8;

    return {
        x: x,
        y: y
    }
}

幽灵节点位置计算不正确,可以从复合节点边界框​​获取。 这样,您就可以完全控制边缘。此外,在导出网络时,您应该考虑丢弃 "assisting edges",因为根据网络的数据,您应该始终能够重绘这些。

PS - 如果复合节点被拖来拖去,您还需要重新计算幽灵节点的位置。