Search code examples
jsfprimefacesjsplumb

How to export image file using PrimeFaces Diagram


I'm using The Diagram component of PrimeFaces. I want to get image (like png) from that component.

How can I do it?

I tried html2canvas and canvg, but I can't get same image. Also I try https://github.com/jsplumb/jsPlumb/issues/35#issuecomment-82196174, but not good.

My code is below.

DiagramShowView.java

package //omitted;

import // omitted
import org.primefaces.model.diagram.DiagramModel;

@Named
@ViewScoped
public class DiagramShowView implements Serializable {

    @Getter
    private DiagramModel flow;

    public void init(){
        this.flow = createDiagramModel(); // omitted createDiagramModel() impementation.
    }
}

Diagram.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<f:metadata><f:viewAction action="#{diagramShowView.init()}"/></f:metadata>
<h:body>
    <h:form id="mainForm">
        <style type="text/css">
            .ui-diagram-element {
                border: 0.1em dotted #d4e06b;
                width: 14em;
                height: 4em;
                line-height: 4em;
                text-align: center;
            }
        </style>
        <div class="ui-g">
            <div class="ui-g-6">
                <p:diagram value="#{diagramShowView.flow}" style="width:100%;height:500px;" id="flow"
                           styleClass="ui-widget-content" var="el">
                    <f:facet name="element">
                        <h:outputText value="#{el}"
                                      style="display:block;margin-top:0.5em;"/>
                    </f:facet>
                </p:diagram>
            </div>
            <div class="ui-g-6">
                <p id="copy"/>
            </div>
        </div>
        <script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
        <script type="text/javascript" src="https://canvg.github.io/canvg/demo/v2/canvg.js"/>
        <script type="text/javascript">
            let el = document.getElementById("mainForm:flow");
            html2canvas(document.getElementById("mainForm:flow"), {
                width: el.scrollWidth,
                height: el.scrollHeight
            }).then(function (canvas) {
                // this code copy from github issue
                ctx = canvas.getContext('2d');
                $flows = $('> svg', el);
                $flows.each(function () {
                    $svg = $(this)
                    offset = $svg.position();
                    svgStr = this.outerHTML;
                    ctx.drawSvg(svgStr, offset.left, offset.top);
                });
                $endpoints = $('._jsPlumb_endpoint > svg', el);
                $endpoints.each(function () {
                    $svg = $(this)
                    offset = $svg.parent().position();
                    svgStr = this.outerHTML;
                    ctx.drawSvg(svgStr, offset.left, offset.top);
                });
                // end of copy code.

                document.getElementById("copy").appendChild(canvas);
            });
        </script>
    </h:form>
</h:body>
</html>

The browser output below. The left component is darwn by jsf. The right component is used by html2canvas and canvg.js.

enter image description here


Solution

  • I was able to solve a part by myself. The reason was that the image are need more bigger area.The answer is in below post.

    HTML2Canvas does not render full div, only what is visible on screen?