示例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%'
},
}])
我得到这样的曲线:
直线曲线样式也是如此。
如何为循环绘制另一个边缘形式?
最佳答案
不确定如果不 fork 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
}
}
Ghost节点位置计算不正确,可以从复合节点边界框中获取。 这样,您就可以完全控制边缘。此外,在导出网络时,您应该考虑丢弃“辅助边”,因为根据网络的数据,您应该始终能够重新绘制这些边。
PS - 如果复合节点被拖动,您还需要重新计算幽灵节点位置。
关于cytoscape.js - 我们可以为循环边缘类型或子父边缘选择其他边缘形式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61922973/