You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dash应用中导出全尺寸Cytoscape图谱为图片?

解决Dash Cytoscape完整图谱导出为PNG的问题

问题说明

使用Python Dash的Cytoscape组件构建故事编排交互式流程图时,场景节点及关联边组成的图谱常超出屏幕尺寸。当前通过generateImage回调仅能捕获屏幕可见区域的内容,缩小视图虽能容纳全图谱但会导致细节模糊;尝试过全页截图方案,因图谱画布超出网页范围无效。

当前代码

@self.app.callback(
        Output("network", "generateImage"),
        Input('dashboard-export-project-button', 'n_clicks'),
        prevent_initial_call=True
        )
    def get_image(export_clicks):

        # Get the timezone
        local_tz = pytz.timezone('My Country')

        # Get the current time in UTC
        current_time_utc = datetime.utcnow()

        # Convert the UTC time to the Local timezone
        current_time = current_time_utc.replace(tzinfo=pytz.utc).astimezone(local_tz)

        time_stamp = current_time_local.strftime("%d/%m/%Y - %H:%M")

        # File type to output of 'svg, 'png', 'jpg', or 'jpeg' (alias of 'jpg')
        ftype = "png"

        # 'store': Stores the image data in 'imageData' !only jpg/png are supported
        # 'download'`: Downloads the image as a file with all data handling
        # 'both'`: Stores image data and downloads image as file.
        action = 'store'

        if ctx.triggered:
            if ctx.triggered_id == "dashboard-export-project-button":
                action = "download"

        return {
            'type': ftype,
            'action': action,
            'filename': f'{self.project.title} - {time_stamp}',
        }

解决方案

方案1:临时适配布局后导出

通过临时将Cytoscape布局切换为fit模式,让所有节点自动适配容器可见区域,导出完成后恢复原布局,避免细节模糊。

修改后的回调代码:

from dash import ctx, Input, Output, State, no_update
import pytz
from datetime import datetime

@self.app.callback(
    [Output("network", "generateImage"), Output("network", "layout")],
    Input('dashboard-export-project-button', 'n_clicks'),
    State("network", "layout"),
    prevent_initial_call=True
)
def export_full_graph(export_clicks, original_layout):
    # 处理时间戳
    local_tz = pytz.timezone('My Country')
    current_time_utc = datetime.utcnow()
    current_time = current_time_utc.replace(tzinfo=pytz.utc).astimezone(local_tz)
    time_stamp = current_time.strftime("%d/%m/%Y - %H:%M")

    if ctx.triggered_id == "dashboard-export-project-button":
        # 临时设置fit布局,让所有节点完整显示
        fit_layout = {
            'name': 'fit',
            'padding': 50  # 预留边距防止节点被截断
        }
        return (
            {
                'type': 'png',
                'action': 'download',
                'filename': f'{self.project.title} - {time_stamp}',
            },
            fit_layout
        )
    # 无触发时保持原状态
    return (no_update, original_layout)

补充说明:可添加额外回调监听generateImage的imageData变化,在导出完成后自动恢复原布局,避免视图持续变化。

方案2:通过JavaScript获取完整SVG转PNG

直接利用Cytoscape的原生API获取完整图谱的SVG数据,再通过Canvas转换为PNG下载,无需调整视图,导出内容清晰完整。

添加客户端回调代码:

from dash import Input, Output, State

# 新增一个dummy组件用于触发客户端回调
self.app.clientside_callback(
    """
    function(n_clicks, project_title) {
        if (!n_clicks) return;
        // 获取Cytoscape实例
        const cy = document.getElementById('network')._cy;
        // 获取完整图谱的SVG数据
        const svgContent = cy.svg({ full: true });
        
        // 将SVG转换为PNG
        const img = new Image();
        img.onload = function() {
            const canvas = document.createElement('canvas');
            canvas.width = img.width;
            canvas.height = img.height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            
            // 触发下载
            canvas.toBlob(function(blob) {
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                const timestamp = new Date().toLocaleString().replace(/[/:,]/g, '-');
                a.download = `${project_title} - ${timestamp}.png`;
                a.click();
                URL.revokeObjectURL(url);
            }, 'image/png');
        };
        img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgContent);
    }
    """,
    Output('dummy-output', 'children'),  # 无需实际输出,仅作为回调载体
    Input('dashboard-export-project-button', 'n_clicks'),
    State('project-title', 'children'),  # 替换为你存储项目标题的组件ID
    prevent_initial_call=True
)

优势:无视图闪烁,直接导出完整清晰的图谱,无需依赖后端额外处理。

内容的提问来源于stack exchange,提问作者coco.abutbul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 18:42:52