Can mxGraph export graphs as PDFs?

后端 未结 2 1805
一个人的身影
一个人的身影 2021-02-09 12:00

I am working on a project that uses mxGraph where I am required to export a high resolution output in PDF for a service process diagram. I\'ve tried recreating the graph using J

相关标签:
2条回答
  • 2021-02-09 12:39

    I'll explain the case of a client initiated request, where the diagram is displayed on the browser when the request is made. This is the standard case, mxGraph transmits an XML representation of the graph using custom graphics primitives and these are received on the server and decoded either by the Java or .NET back-ends.

    The reason for the need for the graph being displayed is there are certain text measurements that are hard to recreate outside of a browser environment.

    On the client side you need to create the required immediate XML using, say, the diagrameditor.html example as a guide:

    var exportImage = function(editor)
    {
        var graph = editor.graph;
        var scale = graph.view.scale;
        var bounds = graph.getGraphBounds();
    
            // New image export
        var xmlDoc = mxUtils.createXmlDocument();
        var root = xmlDoc.createElement('output');
        xmlDoc.appendChild(root);
    
        // Renders graph. Offset will be multiplied with state's scale when painting state.
        var xmlCanvas = new mxXmlCanvas2D(root);
        xmlCanvas.translate(Math.floor(1 / scale - bounds.x), Math.floor(1 / scale - bounds.y));
        xmlCanvas.scale(scale);
    
        var imgExport = new mxImageExport();
        imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas);
    
        // Puts request data together
        var w = Math.ceil(bounds.width * scale + 2);
        var h = Math.ceil(bounds.height * scale + 2);
        var xml = mxUtils.getXml(root);
    
        // Requests image if request is valid
        if (w > 0 && h > 0)
        {
            var name = 'export.png';
            var format = 'png';
            var bg = '&bg=#FFFFFF';
    
            new mxXmlRequest(editor.urlImage, 'filename=' + name + '&format=' + format +
                    bg + '&w=' + w + '&h=' + h + '&xml=' + encodeURIComponent(xml)).
                    simulate(document, '_blank');
        }
    };
    

    Where editor.urlImage is the URL of the image generating servlet, in the case for a Java back-end.

    On the server-side, in the case of Java, look at the java/examples/com/mxgraph/examples/web/ExportServlet.java. That looks at the "format" parameter passed up, and if 'pdf', the writePdf() method is invoked.

    That method creates an PdfWriter and renders the graphics primitives to a Java Swing Graphics2D using the Java favoured part of mxGraph.

    This example writes the PDF result directly to the outstream of the servlet repsonse in this line:

    PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
    

    You could map the output to any stream.

    Note that you need to setup iText to map every font you need in the PDF. This isn't always ideal for a large number of fonts. It's worth testing a few cases of the export to see if the output is good enough for your requirements. We're currently researching the use of PhantomJS for the export. If the Java export isn't good enough, please post another question regarding using PhantomJS and I'll detail the process for that.

    iText is provided as an example PDF library to use, it's easier since it's under an open source library. It's possibly not the best suited library, we didn't find it easy to work with for this specific scenario. You might also want to investigate other Java PDF generation libraries.

    Also note that the .NET back-end only supports raster image generation in dotnet/aspnet/Export.ashx, there's no known open source PDF library to supply as an example there.

    0 讨论(0)
  • 2021-02-09 12:56

    Full vector solution:

    1. Set mxClient.NO_FO = true;
    2. Export SVG to PDF by svg2pdf.js
    3. Write all DIV's text to pdf by jsPDF

    Example:

    let pdf = new jsPDF('p', 'pt', 'a4', false, false);
    mxClient.NO_FO = true;
    let graph = Draw(drawdiv, false);
    let svgEl = drawdiv.children[1];
    //draw svg:
    svg2pdf(svgEl, pdf, {
      xOffset: pdfPageDefaultOffsetX,
      yOffset: pdfOffsetY,
      scale: divToPdfRatio
    });
    //draw text:
    for (let child of drawdiv.children) {
      if (child.tagName === 'DIV') {
        let splitText = pdf.splitTextToSize(child.innerText, Math.ceil((childSizes.width) * divToPdfRatio));
        pdf.text(pdfPageDefaultOffsetX + (child.offsetLeft * divToPdfRatio), textPositionTop, splitText, {
          align: child.style.textAlign,
          lineHeightFactor: 1,
        });
      }
    }
    pdf.save('Test.pdf');
    
    0 讨论(0)
提交回复
热议问题