html2canvasとは?
htmlの要素を解析してcanvas化するライブラリです。
html2canvas - Screenshots with JavaScript
例えばとあるdivにcssでborderが指定されていて、子要素にtextNodeがあったならば、
divと同じ大きさのblockを作って、strokeでborder引いて、textで文字を書いて、同じ見た目のcanvas要素化してくれる、というかんじです。
これを実際にやろうと考えた場合、
タグは見た目にさして関係無いからいいとしても、全cssを変換する処理を用意するなんて、現実的でなくね?
とかなると思いますが、そのものズバリ、html2canvasのgithubを見てもらうとわかりますが、cssごとの変換処理が書かれていたりします。とんでもないですね。
html2canvasを使ってみる
何も考えずに使う場合、使い方はシンプルです。
<script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script> <script type="text/javascript"> var content = document.getElementById("content"); html2canvas(content).then(canvas => { ... }); </script>
これだけで渡した要素がcanvas化されたものが返ってきます。
せっかくなので、Googleのフィードバック送信時の処理
(表示中の画面にマーキングしてお問い合せする機構
ここの「フィードバックを送信」でできるやつ)
みたいなのをやってみます。
ui
適当にベタhtmlで
・画面キャプチャするボタン
・画面キャプチャしたものを入れる要素
・マークした結果をキャプチャするボタン
・マークした結果を表示する要素
を置きます。
<button id="execButton" class="exec-btn" onclick="h2c();"><img src="camera.svg"/></button> <div id="screenshot" class="screenshot" style="display:none;"></div> <button id="okButton" class="ok-btn" onclick="c2i();" style="display:none;"><img src="done.svg"/></button> <div id="resultBg" class="result-bg" onclick="iClose();" style="display:none;"><img id="result" class="result"/></div>
画面をキャプチャする処理
画面をhtml2canvasにお願いしてcanvas化してもらいます。
要素の表示/非表示の切り替えに手抜き感が伺えますが、気にしない。
function h2c() { var content = document.getElementById("content"); html2canvas(content).then(canvas => { var ss = document.getElementById("screenshot"); ss.appendChild(canvas); initSelector(canvas); ss.style.display = ""; content.style.display = "none"; document.getElementById("execButton").style.display = "none"; document.getElementById("okButton").style.display = ""; }); }
canvasにマークする処理
所謂、自由選択ツールのようなことをします。
イベントの貼り方に手抜き感が伺えますが、良い子はマネしないでね!
function initSelector(screenshot){ var selector = document.createElement("canvas"); with (selector) { width = screenshot.width; height = screenshot.height; className = "selector"; style.zIndex = (screenshot.style.zIndex || 0) + 1; } buildSelector(selector).selectEnd = function(r) { with (screenshot.getContext("2d")) { fillStyle = "#ffeb3ba1"; fillRect(r.sx, r.sy, r.ex, r.ey); } } screenshot.parentElement.appendChild(selector); } function buildSelector(canvas) { var context = canvas.getContext("2d"); with (context) { setLineDash([6, 3]); strokeStyle = "#3e3e3ecf"; } context.rect = { sx: 0, sy: 0, ex: 0, ey: 0, dirty: false }; context.selectStarted = false; context.clear = function(dirty) { this.rect.dirty = dirty; this.clearRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight); } context.select = function() { this.clear(true); this.strokeRect(this.rect.sx, this.rect.sy, this.rect.ex, this.rect.ey); } context.selectEnd = null; canvas.addEventListener("mousedown", function (e) { context.rect.sx = e.pageX; context.rect.sy = e.pageY; context.selectStarted = true; }, false); canvas.addEventListener("mousemove", function (e) { if (!context.selectStarted) return; context.rect.ex = e.pageX - context.rect.sx; context.rect.ey = e.pageY - context.rect.sy; context.select(); }, false); canvas.addEventListener("mouseup", function onMouseUp (e) { if (context.rect.dirty) { context.clear(false); if (context.selectEnd) context.selectEnd(context.rect); } context.selectStarted = false; }, false); return context; }
マークした結果をキャプチャする処理
canvasをインラインイメージ化してimgタグにぶち込みます。
それ以外でやってることは例によって手抜きですね。
ついでに、プレビューを閉じて最初に戻る処理も書いておきます。
function c2i() { var ss = document.getElementById("screenshot"); var canvas = ss.firstChild; var selector = ss.lastChild; document.getElementById("result").src = canvas.toDataURL(); ss.removeChild(canvas); ss.removeChild(selector); ss.style.display = "none"; document.getElementById("okButton").style.display = "none"; document.getElementById("resultBg").style.display = ""; } function iClose() { document.getElementById("resultBg").style.display = "none"; document.getElementById("execButton").style.display = ""; document.getElementById("content").style.display = ""; }
当たり前といえば当たり前ですが、画面のキャプチャなので、それっぽい画面がなければ意味がない・・・
でも、出来上がっている画面を用意するのって地味に面倒なんですよね。。。というわけで、github pageのデフォルトを利用します。
で、出来上がったのが以下。
Welcome to GitHub Pages
完全版のソースはこれ
なんとも簡単にそれっぽくなりました。
使い所は限られるとは思いますが、アイデア次第では色々なことができそうです。
いじょ