最近プロジェクトを書く際にページのスクリーンショット機能を実現できるhtml2canvas.jsを使っていたのですが、色々落とし穴に遭遇したのでその記録を兼ねてエッセイを書きます。
html2canvasを使用すると、ビジュアルインターフェイスのみがキャプチャできる、スクリーンショットに背景色がない、svgタグがキャプチャできないなどの問題が発生する可能性があります。以下に詳しく説明します。
1.html2canvas.jsをインポートする言うまでもなく、これは github から入手できます: https://github.com/niklasvh/html2canvas
リンクを直接インポートすることもできます: <script src=https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js></script>
使用方法も非常に簡単で、特定の API をオンラインで見つけて、image/png を使用して PNG 画像を生成することができます。
このうち、$(#xxx) はインターセプトしたい div です。もちろん、ドキュメントを通じて取得することもできます。
html2canvas($(#xxx), { onrendered: function (canvas) { var url = Canvas.toDataURL(image/png); window.location.href = url; } });
jpg、image/jpeg などの他のタイプの画像の場合は、自分で API にクエリを実行できます。
実はここで簡単なスクリーンショットが完成しました。インターフェースがもう少し複雑だと、さまざまな落とし穴が現れる可能性があります。それを一つずつ解決していきましょう。
2. svgがインターセプトできない問題div をインターセプトするときに、div 内に svg タグがある場合、通常の状況ではインターセプトできません。たとえば、フローチャートをインターセプトすると、次のような結果が得られます。
フローチャートの行がインターセプトされていないことがわかります。つまり、SVG がインターセプトされていないことがわかります。このときの解決策は、SVG を Canvas に変換してスクリーンショットを撮り、コードを直接アップロードすることです。
ここでの each ループは、すべての svg タグをループし、それらをすべて Canvas に変換します。
if (typeof html2canvas !== 'unknown') { //以下は svg の処理です var nodesToRecover = []; var nodesToRemove = [] svgElem = cloneDom.find('svg'); (インデックス、ノード) { varparentNode = node.parentNode var svg = node.outerHTML.trim(); var Canvas = document.createElement('canvas'); Canvas.width = 650; canvg(canvas, svg); if (node.style.position += node.style) .position; キャンバス.スタイル.左 += ノード.スタイル.左; キャンバス.スタイル.トップ += ノード.スタイル.トップ }子: ノード }); 親ノード.削除子(ノード); 親: 親ノード, 子: キャンバス });
ここでは Canvg.js とその依存ファイル rgbcolor.js が必要です。これらはインターネットから直接ダウンロードすることも、直接インポートすることもできます。
3. 背景透過の問題デフォルトでは透明なので、これは実際には非常に簡単です。次のように、背景色を追加するためのパラメーターbackground があります。
html2canvas(cloneDom, { onrendered: function(canvas) { var url =canvas.toDataURL(image/png); }, background:#fafafa});4. 目に見える部分しか撮影できない問題
インターセプトする必要がある div がインターフェイスを超える場合、上の図に示すように、コンテンツの半分しか存在せず、html2canvas がインターセプトできないという問題が発生する可能性があります。隠しDOM。
したがって、現時点での解決策は、クローン作成を使用し、インターセプトする必要がある部分のコピーをページの下部に配置し、html2canvas を使用して完全な div をインターセプトし、インターセプトが完了したら、この部分を削除します。完全なコードは次のとおりです。
function showQRCode() {scrollTo(0, 0); //ノードをクローンします。デフォルトは false、つまりメソッド属性はコピーされず、true はすべてのコピーです。 var cloneDom = $(#d1).clone(true); //クローン作成されるノードよりも低い場合に限り、クローン作成されたノードの z-index 属性を設定します。 cloneDom.css({ 背景色: #fafafa, 位置: 絶対, トップ: 0px, z-index: -1, 高さ: 798, 幅: 650 }); if (typeof html2canvas !== 'unknown') { / /以下はsvgの処理です var nodesToRecover = [] var nodesToRemove = []; cloneDom.find('svg');//divReport はピクチャにインターセプトする必要がある dom の ID です svgElem.each(function (index, node) { varparentNode = node.parentNode; var svg = node.outerHTML .trim(); var Canvas = document.createElement('canvas'); Canvas.width = 650; canvg(canvas, svg); if (node.style.position) {キャンバス.スタイル.ポジション += ノード.スタイル.左 += ノード; .style.top; } ノードToRecover.push({ 親: 親ノード, 子: ノード }); ノードToRemove.push({ 親: 親ノード: Canvas });parentNode.appendChild(canvas); //クローンノードを本体に動的に追加します。 $(body).append(cloneDom); html2canvas(cloneDom, { onrendered: function(canvas) { var url =canvas.toDataURL(image/png); window.location.href = url ; cloneDom.remove(); //クローンされたコンテンツをクリアします}、背景:#fafafa }) } }
ここでは、まずインターセプトする div をクローンし、見苦しいインターフェイスが発生しないように z-index を最小に設定します。次に、上で分析した svg が処理され、最後にクローン ノードがボディに追加されます。
onrendered では、location.href を直接使用して画像の表示、保存にジャンプしたり、img の src に URL を書き込んで、$('#imgId').attr('src など) のインターフェイスに表示したりできます。 '、url);
最後に、キャプチャしたばかりの画像をインターフェイスに表示できます。
5. 画像をアップロードしてデータベースに保存し、インターフェイスに表示する画像を取得します。URL を取得したので、それをバックエンドにアップロードしてデータベースに保存し、表示されている別のインターフェイスにロードする必要があります。私は通常、BLOB ストレージではなく URL を使用して画像パスを保存することに慣れています。
別のインターフェイスで画像を取得する必要があるため、画像を Web アプリと同じレベルのリソース ディレクトリに保存しました。コードは次のとおりです。
//ピクチャを保存し、ピクチャのパスを返します BASE64Decoder decoder = new BASE64Decoder(); byte[] b = decoder.decodeBuffer(product.getProPic().substring(data:image/png;base64,.length()); ByteArrayInputStream bais = new ByteArrayInputStream(b); url = user_resource + File.separator + img + File.separator + product_+UUID.randomUUID().toString().replace(-, )+.png; 文字列 totalUrl = System.getProperty(root) + ファイル w2 =新しいファイル(totalUrl); ImageIO.write(bi1, png, w2); //画像の相対パスをデータベースに保存します int res = productMapper.insertSelective(product); //データベースに追加します
ここには他のロジックが関係しているため、コードの一部のみが含まれています。
ここでは BASE64Decoder を使用して画像を保存します。次は画像の URL であるため、画像を取得した後、substring を使用して data:image/png;base64 のコンテンツをインターセプトする必要がありurl.substring(data:image/png;base64,.length())
。 url.substring(data:image/png;base64,.length())
。
パスについては、上記のコードの URL はデータベースに保存した内容であり、totalUrl は ImageIO の実際の書き込み操作中に保存された実際のパスです。getProperty() メソッドで取得したプロジェクトのルート ディレクトリを使用できます。 web.xmlに以下の内容を設定し、System.getProperty(root)を利用することができます。
<!-- プロジェクトのルート ディレクトリを取得するようにシステムを構成します --><context-param> <param-name>webAppRootKey</param-name> <param-value>root</param-value></context-param ><リスナー > <リスナークラス> org.springframework.web.util.WebAppRootListener </リスナークラス></リスナー>
これで、画像の URL がデータベースに保存され、画像自体は Tomcat の下のプロジェクトのディレクトリに保存されます。
最後に、インターフェイスから取得するには、現在の URL < img class =depot-img src =<%=request.getContextPath()%>/`+e.proPic+` >
の前にプロジェクト名を追加するだけです。
次に、インターフェイスに画像が表示されることがわかります。
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。