/
lemut
/
cifranet
Обзор
Документация
Войти
/
lemut
/
cifranet
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
hover.py
133 строки
6 KB
lemut
first_commit
23 июл 2026, 11:49
23 июл 2026, 11:49
910f940
Код
Авторство
О чём код?
import dash from dash import html, dcc, Input, Output, State import dash_cytoscape as cyto app = dash.Dash(__name__) # Элементы графа (узлы и рёбра) elements = [ # Узлы {'data': {'id': 'node1', 'label': 'Сервер', 'description': 'Главный сервер БД', 'type': 'server'}}, {'data': {'id': 'node2', 'label': 'Клиент A', 'description': 'Рабочая станция отдела продаж', 'type': 'client'}}, {'data': {'id': 'node3', 'label': 'Клиент B', 'description': 'Рабочая станция бухгалтерии', 'type': 'client'}}, {'data': {'id': 'node4', 'label': 'API Gateway', 'description': 'Точка входа для внешних запросов', 'type': 'gateway'}}, # Рёбра {'data': {'source': 'node1', 'target': 'node2', 'label': 'SQL', 'description': 'Запросы к БД'}}, {'data': {'source': 'node1', 'target': 'node3', 'label': 'SQL', 'description': 'Запросы к БД'}}, {'data': {'source': 'node4', 'target': 'node1', 'label': 'HTTP', 'description': 'Перенаправление запросов'}}, ] app.layout = html.Div([ html.H3("Граф с информацией при наведении"), html.Div([ cyto.Cytoscape( id='cytoscape-tooltip', elements=elements, layout={'name': 'breadthfirst'}, style={'width': '70%', 'height': '500px', 'border': '1px solid #ccc'}, stylesheet=[ { 'selector': 'node', 'style': { 'label': 'data(label)', 'width': '60px', 'height': '60px', 'background-color': '#6FA8DC', 'color': '#fff', 'font-size': '12px', 'text-valign': 'center', 'text-halign': 'center' } }, { 'selector': 'edge', 'style': { 'label': 'data(label)', 'width': 2, 'line-color': '#999', 'target-arrow-color': '#999', 'target-arrow-shape': 'triangle', 'curve-style': 'bezier' } }, # Для наглядности — разные цвета узлов по типу { 'selector': '[type = "server"]', 'style': {'background-color': '#FF6B6B'} }, { 'selector': '[type = "gateway"]', 'style': {'background-color': '#4ECDC4'} } ] ), html.Div( id='tooltip-output', style={ 'width': '28%', 'marginLeft': '2%', 'padding': '15px', 'border': '1px solid #ddd', 'borderRadius': '8px', 'backgroundColor': '#f9f9f9', 'fontFamily': 'Arial, sans-serif', 'verticalAlign': 'top', 'minHeight': '200px' }, children=[ html.H4("ℹ️ Информация об элементе"), html.P("Наведите курсор на узел или ребро", style={'color': '#666'}) ] ) ], style={'display': 'flex', 'flexDirection': 'row'}) ]) @app.callback( Output('tooltip-output', 'children'), Input('cytoscape-tooltip', 'mouseoverNodeData'), Input('cytoscape-tooltip', 'mouseoverEdgeData'), prevent_initial_call=True ) def display_tooltip(node_data, edge_data): """ При наведении на узел или ребро обновляем содержимое панели. Если наведено на узел — показываем данные узла. Если на ребро — показываем данные ребра. """ ctx = dash.callback_context if not ctx.triggered: # если колбэк вызван без события (не должно быть, но на всякий случай) return [html.H4("ℹ️ Информация об элементе"), html.P("Наведите курсор на узел или ребро", style={'color': '#666'})] trigger_id = ctx.triggered[0]['prop_id'].split('.')[0] if trigger_id == 'cytoscape-tooltip' and node_data: # Наведены на узел return [ html.H4(f"🔵 Узел: {node_data.get('label', '—')}"), html.P(f"ID: {node_data.get('id', '—')}"), html.P(f"Описание: {node_data.get('description', 'нет данных')}"), html.P(f"Тип: {node_data.get('type', 'не указан')}"), html.Hr(), html.I("Информация появляется при наведении") ] elif trigger_id == 'cytoscape-tooltip' and edge_data: # Наведены на ребро return [ html.H4(f"🔗 Ребро: {edge_data.get('label', '—')}"), html.P(f"От: {edge_data.get('source', '?')} → {edge_data.get('target', '?')}"), html.P(f"Описание: {edge_data.get('description', 'нет данных')}"), html.Hr(), html.I("Информация появляется при наведении") ] # Если данных нет (например, при mouseout) – показываем нейтральное сообщение return [html.H4("ℹ️ Информация об элементе"), html.P("Наведите курсор на узел или ребро", style={'color': '#666'})] if __name__ == '__main__': app.run(debug=True)