Clipboard API があった
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 2
◆ 簡単にクリップボードにコピーと貼り付けができる
◆ 切り取りはコピーのときに対象を消せばいい
◆ 画像もコピー可能
◆ 貼り付け(読み取り)にはユーザの許可が必要
◆ navigatgor.clipboard が存在するのは https のみ
◆ 切り取りはコピーのときに対象を消せばいい
◆ 画像もコピー可能
◆ 貼り付け(読み取り)にはユーザの許可が必要
◆ navigatgor.clipboard が存在するのは https のみ
これまでブラウザでクリップボード操作をするには
のように execCommand を使っていました
IE でも動く古くからあるものですが その分扱いづらいものでした
textarea を作ってそこに文字列を入れて選択してから execCommand でコピーとすごく手間がかかります
それに textarea を document 以下にアタッチするかどうかで挙動が変わったりなど困ることもありました
使い方は簡単です
これを実行すれば copied という文字がクリップボードにコピーされます
コンソールで実行する場合は ページにフォーカスがないといけないので
のように setTimeout で実行を遅らせて その間に devtools からページの方にフォーカスを移します
実行されるタイミングでページにフォーカスがないと DOMException が発生します
コンソールに copied メッセージが表示されるとコピーできてます
画像の場合は navigator.clipboard の write メソッドを使います
w3c のドラフトでは Blob データを write に渡していますが これだとエラーになりました
上の方の定義では write には ClipboardItems を渡すようになっていて
という定義があるので ClipboardItem の配列を渡すのが正しいようです
ClipboardItem のコンストラクタでは mime type をキーにした blob のオブジェクトを渡します
普通に mime type と blob を渡せば良いと思うのですが なんでこんな変なオプションのとり方何でしょう?
異なる mime type で複数設定できそうですが OS とブラウザの対応状況でコピー対象が変わったりするのでしょうか
それにしては優先順位も設定できないですし ドキュメントを検索してもそれっぽいのは見当たりませんでした
入力した文字を canvas に描いて その画像をコピーできます
DEMO (Gist)
read と readText メソッドです
ただ こっちはユーザからの許可が必要です
クリップボードには個人情報が書いてるテキストを保存してることもあるので 信頼できないページが勝手に情報読み取るのはセキュリティ的に良くないですからね
許可を取るのは 特になにかする必要はなく readText メソッドを実行したらブラウザが許可していいですかという通知を表示します
デスクトップ通知とか 位置情報とかと同じようなやつです
そこで許可されればクリップボードのデータを取得できます
さっきまでの書き込みの方は許可不要でできます
こっちの場合は悪用しようとしても 嫌がらせみたいなメッセージや怖い画像を知らないうちにコピーするくらいで セキュリティ的な問題はないはずなので許可はいらないです
これらでも十分迷惑行為ですが そういうページを開いてる以上 クリップボード関係なく コピーするテキストや画像を直接見せられることだってありえるのでクリップボードを許可制するほどでもないのでしょう
http ページだとこれまでの execCommand に頼ることになります
document.execCommand("copy")
のように execCommand を使っていました
IE でも動く古くからあるものですが その分扱いづらいものでした
textarea を作ってそこに文字列を入れて選択してから execCommand でコピーとすごく手間がかかります
それに textarea を document 以下にアタッチするかどうかで挙動が変わったりなど困ることもありました
Clipboard API
そんなクリップボード操作ですが いつのまにか Clipboard API というものができていました使い方は簡単です
navigator.clipboard.writeText("copied")
これを実行すれば copied という文字がクリップボードにコピーされます
コンソールで実行する場合は ページにフォーカスがないといけないので
setTimeout(async () => {
await navigator.clipboard.writeText(new Date())
console.log("copied")
}, 1000)
のように setTimeout で実行を遅らせて その間に devtools からページの方にフォーカスを移します
実行されるタイミングでページにフォーカスがないと DOMException が発生します
コンソールに copied メッセージが表示されるとコピーできてます
画像もコピーできる
コピーはテキストだけじゃなくて画像も可能です画像の場合は navigator.clipboard の write メソッドを使います
w3c のドラフトでは Blob データを write に渡していますが これだとエラーになりました
上の方の定義では write には ClipboardItems を渡すようになっていて
typedef sequence<ClipboardItem> ClipboardItems;
という定義があるので ClipboardItem の配列を渡すのが正しいようです
ClipboardItem のコンストラクタでは mime type をキーにした blob のオブジェクトを渡します
普通に mime type と blob を渡せば良いと思うのですが なんでこんな変なオプションのとり方何でしょう?
異なる mime type で複数設定できそうですが OS とブラウザの対応状況でコピー対象が変わったりするのでしょうか
それにしては優先順位も設定できないですし ドキュメントを検索してもそれっぽいのは見当たりませんでした
DEMO
画像をコピーする簡単なページを作ってみました入力した文字を canvas に描いて その画像をコピーできます
<!DOCTYPE html>
<div>
<input type="color" id="color">
<input id="text">
<button id="wac">Write & Copy</button>
</div>
<div>
<canvas id="canvas" width=400 height=40 style="border: 1px solid silver"></canvas>
</div>
<script>
wac.onclick = () => {
const ctx = canvas.getContext("2d")
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = color.value
ctx.font = "20px seif"
ctx.fillText(text.value, 15, 25)
const blob = canvas.toBlob(blob => {
navigator.clipboard.write([
new ClipboardItem({ [blob.type]: blob })
])
})
}
</script>
DEMO (Gist)
Paste
クリップボードへの書き込みだけじゃなくて読み取り(貼り付け)もありますread と readText メソッドです
ただ こっちはユーザからの許可が必要です
クリップボードには個人情報が書いてるテキストを保存してることもあるので 信頼できないページが勝手に情報読み取るのはセキュリティ的に良くないですからね
許可を取るのは 特になにかする必要はなく readText メソッドを実行したらブラウザが許可していいですかという通知を表示します
デスクトップ通知とか 位置情報とかと同じようなやつです
そこで許可されればクリップボードのデータを取得できます
さっきまでの書き込みの方は許可不要でできます
こっちの場合は悪用しようとしても 嫌がらせみたいなメッセージや怖い画像を知らないうちにコピーするくらいで セキュリティ的な問題はないはずなので許可はいらないです
これらでも十分迷惑行為ですが そういうページを開いてる以上 クリップボード関係なく コピーするテキストや画像を直接見せられることだってありえるのでクリップボードを許可制するほどでもないのでしょう
https のみ
navigator.clipboard があるのは https ページのみで http ページだと存在しませんhttp ページだとこれまでの execCommand に頼ることになります