Dagre 节点对齐

问题描述

我用 dagre 创建了一个自上而下的有向图。但有时某些节点的对齐方式会磨损且令人不安(参见打印屏幕:例如,节点 79 与右侧对齐过多)。

我已经使用了图表选项,但我还没有找到确保节点 79 与图表左侧更对齐的解决方案。

dagre 计算节点位置时已经发生了错位,所以我猜问题一定出在 graphlib 设置中,而不是在渲染部分。

我还添加了一部分代码显示我正在使用的设置。

任何帮助将不胜感激!

这是我正在执行的代码

    function showFlowchartSO(JSONstructure) {
    var structure = JSON.parse(JSONstructure);

    // display options
    var options = {
        rankdir: "TB",align: "UL",nodesep: 15,ranksep: 20,ranker: "network-simplex"
    };

    // Create the input graph
    var g = new dagre.graphlib.Graph()
        .setGraph(options)
        .setDefaultEdgeLabel(function () {
            return {};
        });

    // Set nodes
    for (var i = 0; i < structure.Nodes.length; i++) {
        g.setNode(structure.Nodes[i].Id,createNodeDOMObject(structure.Nodes[i]));
    }

    // Set connections
    var connections = structure.Nodes.map(e => e.Dependencies).flat();
    for (let i = 0; i < connections.length; i++) {
        var isSourceNodeChoiceNode = structure.Nodes.find(e => e.Id == connections[i].sourceNodeId).Options.find(e => e.OptionTypeId == 21)?.Active ?? false; // when source node is choice node => we also need to have an or dependency (in the future we need to solve this problem at the source..)

        if (connections[i].DependencyOr || isSourceNodeChoiceNode)
            g.setEdge(connections[i].sourceNodeId,connections[i].TargetNodeId,{ style: "fill: none; stroke: #000; stroke-width: 1px; stroke-dasharray: 5,5; margin: 5px;",arrowheadStyle: "fill: #000" });
        else
            g.setEdge(connections[i].sourceNodeId,connections[i].TargetNodeId);
    }

    dagre.layout(g);

    // Create the renderer
    var render = new dagreD3.render();

    // Set up an SVG group so that we can translate the final graph.
    var svg = d3.select("#network");

    // Run the renderer. This is what draws the final graph.
    render(svg,g);

    // Center the graph
    var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
    var svgGroup = svg.append("g");
    svgGroup.attr("transform","translate(" + xCenterOffset + ",20)");
    svg.attr("height",g.graph().height + 40);
}

function createNodeDOMObject(node) {
    let html;
    let className;

    var command = node?.Properties?.find(e => e.PropertyTypeId == 5)?.Value ?? "";
    var loopBack = node?.Properties?.find(e => e.PropertyTypeId == 1)?.Value ?? "";
    var loopGoto = node?.Properties?.find(e => e.PropertyTypeId == 2)?.Value ?? "";
    var startcapt = node?.Options?.find(e => e.OptionTypeId == 8)?.Active ?? false;
    var stopcapt = node?.Options?.find(e => e.OptionTypeId == 9)?.Active ?? false;
    var simnoloop = node?.Options?.find(e => e.OptionTypeId == 2)?.Active ?? false;
    var update = node?.Options?.find(e => e.OptionTypeId == 12)?.Active ?? false;
    var datacap = node?.Options?.find(e => e.OptionTypeId == 6)?.Active ?? false;


    html = "<div id='node_" + node.Id + "' class='node'>" +
        "<div class='node-left-container'></div>" +
        "<div class='node-loopback'><p>" + (loopBack !== '' ? '< ' : '') + "</p></div>" +
        "<div class='node-loopgoto'><p>" + (loopGoto !== '' ? '> ' + loopGoto : '') + "</p></div>" +
        "<div class='node-level'><p>" + node.Level + "</p></div>" +
        "<div class='node-operation'><p>" + node.Operation + "</p></div>" +
        "<div class='node-equipment'><p>" + (node.Equipment ?? "") + "</p></div>" +
        "<div class='node-command'><p>" + command + "</p></div>" +
        "<div class='node-right-container'></div>" +
        "<div class='node-startcapt'>" + (startcapt ? ">" : "") + "</div>" +
        "<div class='node-simnoloop'>" + (simnoloop ? "||" : "") + "</div>" +
        "<div class='node-stopcapt'>" + (stopcapt ? ">" : "") + "</div>" +
        "</div>";

    if (update) { // UPDATE 
        className = "update-node";
    }

    if (datacap) { // DATACAP
        className += " datacap-node";
    }

    return {
        labelType: 'html',label: html,rx: 5,ry: 5,padding: 0,class: className
    };
}

我想在此问题中添加 JSON 输入文件,但这似乎不可能。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)