根据边的数据和目标的数据选择边
Selecting edges based on both edge's data and target's data
我想要一个边缘匹配的选择器
edge[type="blocker"]
目标匹配
node[status="complete"]
换句话说,是否有一种有效的表达方式:
cytoscape({
...
style: [
...
{
selector: '( node -> node[status="complete"] )[type="blocker"]',
style: {
display: 'none',
},
},
...
],
...
})
我在 documentation 中看不到这样做的方法。
显然,我可以将目标的数据复制到节点的数据中并使用以下命令:
edge[type="blocker"][target_status="complete"]
但是复制数据违背了我作为软件开发人员的每一个本能。
您可以为过滤方法提供功能:
cy.edges().filter(function(ele) {
return ele.data('type') == 'blocker' &&
ele.target().data('status') == 'complete';
})
这个怎么样
编辑:
var selectedEdges = cy.nodes("[status= 'complete']").connectedEdges("[type = 'blocker']);
var selectedEdges.addClass('specialSnowflake')
在您的样式表中,只需定义:
{
"selector": "edge.specialSnowflake",
"style": {
"display": "none"
}
}
没有可以提供帮助的选择器。
但是,可以避免在数据更改时必须手动更新两个元素。
样式 sheet 每次匹配元素的数据更改时都会调用值函数。在其中一个函数中,可以因此在每次更新节点数据时更新传入边的数据,从而自动保持两者的数据同步。
var push_status = function(node) {
node.incomers('edge').forEach( edge => edge.data('target_status', node.data('status')) );
node.outgoers('edge').forEach( edge => edge.data('source_status', node.data('status')) );
};
cytoscape({
...
style: [
...
{
selector: 'node',
style: {
label: node => { push_status(node); return node.data('id'); },
},
},
{
selector: 'edge[type="blocker"][target_status="complete"]',
style: {
display: 'none',
},
},
...
],
...
})
这可以算作黑客攻击,但效果很好。更新节点的数据会更新边的数据,这会导致根据需要应用或取消应用样式。
小心创建无限循环!特别是,修改节点父节点的数据将触发节点样式的计算。这个问题可以通过更换
来避免
ele.data('key', val)
与
// Making changes to a element's data triggers a style recalculation.
// This avoids needlessly triggering the style recalculation.
var set_data = function(node, key, new_val) {
let old_val = node.data(key);
if (new_val != old_val)
node.data(key, new_val);
};
set_data(ele, 'key', val)
如果选择器不够用,那么您可以 (1) 建议一个新功能来增强边缘 ->
选择器,甚至可以为它创建一个 PR,或者 (2) 在样式上使用一个函数属性 而不是。
例如对于 (2):
{ selector: 'edge', style: { display: edgeIsDisplayed } }
函数可以是任何东西,比如edgeIsDisplayed(edge) => edge.data('foo') === 'bar' && edge.target().hasClass('baz')
我想要一个边缘匹配的选择器
edge[type="blocker"]
目标匹配
node[status="complete"]
换句话说,是否有一种有效的表达方式:
cytoscape({
...
style: [
...
{
selector: '( node -> node[status="complete"] )[type="blocker"]',
style: {
display: 'none',
},
},
...
],
...
})
我在 documentation 中看不到这样做的方法。
显然,我可以将目标的数据复制到节点的数据中并使用以下命令:
edge[type="blocker"][target_status="complete"]
但是复制数据违背了我作为软件开发人员的每一个本能。
您可以为过滤方法提供功能:
cy.edges().filter(function(ele) {
return ele.data('type') == 'blocker' &&
ele.target().data('status') == 'complete';
})
这个怎么样 编辑:
var selectedEdges = cy.nodes("[status= 'complete']").connectedEdges("[type = 'blocker']);
var selectedEdges.addClass('specialSnowflake')
在您的样式表中,只需定义:
{
"selector": "edge.specialSnowflake",
"style": {
"display": "none"
}
}
没有可以提供帮助的选择器。
但是,可以避免在数据更改时必须手动更新两个元素。
样式 sheet 每次匹配元素的数据更改时都会调用值函数。在其中一个函数中,可以因此在每次更新节点数据时更新传入边的数据,从而自动保持两者的数据同步。
var push_status = function(node) {
node.incomers('edge').forEach( edge => edge.data('target_status', node.data('status')) );
node.outgoers('edge').forEach( edge => edge.data('source_status', node.data('status')) );
};
cytoscape({
...
style: [
...
{
selector: 'node',
style: {
label: node => { push_status(node); return node.data('id'); },
},
},
{
selector: 'edge[type="blocker"][target_status="complete"]',
style: {
display: 'none',
},
},
...
],
...
})
这可以算作黑客攻击,但效果很好。更新节点的数据会更新边的数据,这会导致根据需要应用或取消应用样式。
小心创建无限循环!特别是,修改节点父节点的数据将触发节点样式的计算。这个问题可以通过更换
来避免ele.data('key', val)
与
// Making changes to a element's data triggers a style recalculation.
// This avoids needlessly triggering the style recalculation.
var set_data = function(node, key, new_val) {
let old_val = node.data(key);
if (new_val != old_val)
node.data(key, new_val);
};
set_data(ele, 'key', val)
如果选择器不够用,那么您可以 (1) 建议一个新功能来增强边缘 ->
选择器,甚至可以为它创建一个 PR,或者 (2) 在样式上使用一个函数属性 而不是。
例如对于 (2):
{ selector: 'edge', style: { display: edgeIsDisplayed } }
函数可以是任何东西,比如edgeIsDisplayed(edge) => edge.data('foo') === 'bar' && edge.target().hasClass('baz')