初めに
クリップボードに格納されている画像をJavaScriptから取り出す機会があったのでメモ。
(例によってニッチなネタです。)
制約
クリップボードの値を取り出すには、ユーザのアクション(ペースト)が必須です。 セキュリティの関係で好き放題アクセスできないようになっているようです。この壁を乗り越えるにはFlashを使うなどの手法があるようですが、この記事ではそれらには触れません。
したがって、ここで紹介する方法の応用場所は相当限られると思います。
たとえば、Qiitaの編集画面でちょっとした画面キャプチャを添付したいときに、いちいちファイルを介さずに添付できるとか・・・どうかなぁ・・・?微妙?
まぁ、こんなアイデアもあるよってことで・・・
サンプル
printscreen(macならctrl + shift + cmd+ 3)で画面キャプチャを取った後、上記ページの「paste image here」という部分でペーストを実行してください。JavaScriptで画像を取得した後、下部のimgタグとtextareaに結果が反映されます。
手順
ブラウザによって手順が若干異なりますが、基本的な発想は同じでです。
contenteditableな要素に画像を張り付けてそれを取ってくるという方法です。
Firefox, IE, Safariの場合
contenteditableな要素に画像を張り付けると、エレメント内にimgタグが挿入されるので、簡単に取得できます。
<div contenteditable="true" width="50px" height="50px">
paste image here
</div>
<img id="outputImage" border="1" width="50%">
<textarea id="outputText"></textarea>
<script>
var element = document.querySelector("[contenteditable]");
element.addEventListener("input", function(e){
// 仮のエレメントを作り、張り付けた内容にimgタグがあるか探す
var temp = document.createElement("div");
temp.innerHTML = this.innerHTML;
var pastedImage = temp.querySelector("img");
// イメージタグがあればsrc属性からbase64が得られるので
// あとは煮るなり焼くなり
if (pastedImage) {
var base64 = pastedImage.src;
document.querySelector("#outputImage").src = base64;
document.querySelector("#outputText").textContent = base64;
}
// contenteditableの内容は戻しておく
this.innerHTML = "paste image here";
})
</script>
Chromeの場合
Chromeの場合は画像を張り付けても画像は挿入されません。しかし、pasteイベントからファイルオブジェクトして画像を取り出すことができます。若干面倒です。
<div contenteditable="true" width="50px" height="50px">
paste image here
</div>
<img id="outputImage" border="1" width="50%">
<textarea id="outputText"></textarea>
<script>
var element = document.querySelector("[contenteditable]");
element.addEventListener("paste", function(e){
// 画像の場合
// e.clipboardData.types.length == 0
// かつ
// e.clipboardData.types[0] == "Files"
// となっているので、それ以外を弾く
if (!e.clipboardData
|| !e.clipboardData.types
|| (e.clipboardData.types.length != 1)
|| (e.clipboardData.types[0] != "Files")) {
return true;
}
// ファイルとして得る
// (なぜかgetAsStringでは上手くいかなかった)
var imageFile = e.clipboardData.items[0].getAsFile();
// FileReaderで読み込む
var fr = new FileReader();
fr.onload = function(e) {
// onload内ではe.target.resultにbase64が入っているのであとは煮るなり焼くなり
var base64 = e.target.result;
document.querySelector("#outputImage").src = base64;
document.querySelector("#outputText").textContent = base64;
};
fr.readAsDataURL(imageFile);
// 画像以外がペーストされたときのために、元に戻しておく
this.innerHTML = "paste image here";
});
</script>