IE11 でもHTMLに動的描画のエリアを画像として保存

先日、html2canvas を使って表示HTMLを画像変換してダウンロード - Oboe吹きプログラマの黙示録
を書いて、IE11では不可能と書きましたが、方法があったのです。
html2canvas を実行した時に、Promise が認識できなくてダメだったのですが、
Polyfill を使えばいいのです。
https://polyfill.io/v2/

HTMLで、

<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>

を書いておくかこのJSを入手して自サーバに置くかします。
これで、html2canvas で画像イメージを取得はできますが、それでもIE11はダウンロードの壁があるので
次に、サーバに一旦、Base64エンコードデータを送信してデコードして返してもらう方法で
ダウンロードができます。
サーバ側アプリに、Wicket を使います。

html2canvas で変換対象のHTML部分は省略します。

<li><button id="outImage" type="button">Download</button>
<a id="download" href="#">Download</a></li>
<input wicket:id="imagedata" id="imagedata" type="hidden">
<button wicket:id="download2nd" id="download2nd" type="button" style="display: none">IE Download</button>

jQuery
Chrome or Edge なら、a tag の href にダウンロードを仕掛けます
そうでなければ、download2nd をtrigger でクリックします。

$("#outImage").on('click', function(){
   var userAgent = window.navigator.userAgent.toLowerCase().toLowerCase();
   console.log("useragent : " + userAgent);
   $('#ua').html(userAgent);
   html2canvas($("#tree"), {
      onrendered : function(canvas){
         if (userAgent.indexOf("chrome/", 0) > 0 || userAgent.indexOf("safari/", 0) > 0){
            var imgageData = canvas.toDataURL("image/png");
            // a id="download" に ダウンロード設定
            $("#download").attr("download", "テスト.png")
            .attr("href", imgageData.replace(/^data:image\/png/, "data:application/octet-stream"));
            // ダウンロード発火
            var evt = document.createEvent("MouseEvents");
            evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            document.getElementById("download").dispatchEvent(evt);
         }else{
            var imgageData = canvas.toDataURL("image/png");
            $('#imagedata').val(imgageData.replace(/^data:image\/png/, "data:application/octet-stream"));
            $('#download2nd').trigger("click");
         }
      }
   });
});

Wicket Base64受信データを受信するフィールド

queue(new Form<Void>("form"));
final HiddenField<String> imagetext_Field = new HiddenField<>("imagedata", new Model<>());
queue(imagetext_Field);

グローバル変数Base64受信データを格納して、以下 AJAXDownload でデコードして
OutputStream に流します。
この AJAXDownload は、https://github.com/yipuran/yipuran-wicketcustom の中にあります。

String datastr;
AJAXDownload downloader = AJAXDownload.of(o->{
   try{
      byte[] b = Base64.getDecoder().decode(datastr);
      o.write(b, 0, b.length);
      o.flush();
      o.close();
   }catch(Exception e){
      throw new RuntimeException(e);
   }
}, ()->"image/png", ()->"テスト.png");

↑の AJAXDownload を submit で呼びます。
ここの SerialThrowableConsumer は、https://github.com/yipuran/yipuran-wicketcustom の中にあります。

queue(new Button("download2nd")
.add(AjaxFormSubmitBehavior.onSubmit("click", SerialThrowableConsumer.of(t->{
   datastr = imagetext_Field.getModelObject().replaceFirst("data:application/octet-stream;base64,", "");
   downloader.callBackDownload(t);
}, (t, x)->{
   t.appendJavaScript("alert('" + x.getMessage() + "');");
}))).add(downloader));

わざわざ、HTMLの input hidden を用意して送信して打ち返すという
方法で安易な方法ですが、確実です。