我正在使用 Dash-Cytoscape 绘制网络,使用
breadthfirst
布局,如此处所述。
我想控制同一级别上元素的出现顺序。 JS API 有
depthSort
参数来实现这一点,但我不知道如何在 Python 中传递前端可以使用的回调。
我尝试过的事情:
"depthSort": lambda a,b: a - b
"depthSort": "(a,b) => a - b"
"depthSort": "function (a,b) { return a - b}"
我想要这个:
1
3 2
但我得到的是这样的:
1
2 3
from dash import Dash
import dash_cytoscape as cyto
app = Dash(__name__)
app.layout = cyto.Cytoscape(
elements=[
{"data": {"id": "1", "label": "1"}},
{"data": {"id": "2", "label": "2"}},
{"data": {"id": "3", "label": "3"}},
{"data": {"source": "1", "target": "2"}},
{"data": {"source": "1", "target": "3"}},
],
layout={
"name": "breadthfirst",
"roots": ["1"],
# "depthSort": ?
},
)
app.run_server(debug=True)
Python 不支持需要 JS 函数的选项,因为它意味着将函数作为字符串传递,因此需要 Cytoscape.js
eval
uate 任意字符串,这可能是维护者不希望看到的安全原因。
也就是说,Dash 支持客户端回调(JS),因此我们仍然可以在回调中分配函数:
from dash import Dash, Output, Input, State
import dash_cytoscape as cyto
app = Dash(__name__)
app.layout = cyto.Cytoscape(
id="cyto",
elements=[
{"data": {"id": "1", "label": "1"}},
{"data": {"id": "2", "label": "2"}},
{"data": {"id": "3", "label": "3"}},
{"data": {"source": "1", "target": "2"}},
{"data": {"source": "1", "target": "3"}},
],
layout={
"name": "breadthfirst",
"roots": ["1"]
}
)
app.clientside_callback(
"""
function (id, layout) {
layout.depthSort = (a, b) => b.data('id') - a.data('id');
cy.layout(layout).run();
return layout;
}
""",
Output('cyto', 'layout'), # update the (dash) cytoscape component's layout
Input('cyto', 'id'), # trigger the function when the Cytoscape component loads (1)
State('cyto', 'layout'), # grab the layout so we can update it in the function
prevent_initial_call=False # ensure (1) (needed if True at the app level)
)
app.run_server(debug=True)
cy.layout(layout).run()
,因为没有添加/删除元素,所以它不会自动运行。