ツイッターのツイートとかで画像をクリップボードから貼り付けられたけど
雑に(MDN内で検索で)やりかた調べた
雑すぎて最初に辿りついたのは
ClipboardAPIなるもので、これパーミッションが必要とかで、何か違うなーって…
ためしに実行してみたらパーミッション求められて、ツイッターとかでそんなの無かったと、コレ違うと
もうちょっと調べてみたら
普通にpasteイベントってのが存在
Element: paste イベント - Web API | MDN
これ試したら普通にいけた
pasteイベントで来るイベントオブジェクトかwindowオブジェクトか(ブラウザによる?)で
なんかclipboardDataというプロパティ(?)があるらしく
こいつの型がDataTransferというやつで
これのtypesプロパティでMIMEで画像ファイルとしてクリップボードにあって(任意の画像コピーがどういう形式かは知らんけど、OSやアプリによる?)
手前環境ではimage/pngで入ってて
filesのプロパティからFileオブジェクトとして取得できて
FileオブジェクトならURL.createObjectURL()メソッドでimgタグに表示できるな、と
んで、試したら
うまくいった
おわり
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<textarea></textarea>
<output></output>
<img width="100" height="100" style="border: 5px dotted red;" src="./img/dog.jpg">
<script>
function output(s) {
const o = document.querySelector('body > output');
o.textContent = o.textContent + '[[' + s.toString() + ']]';
}
let buf = [];
document.querySelector('body > textarea')
.addEventListener('paste', event => {
for (const x of buf) {
URL.revokeObjectURL(x);
document.querySelector('body > img').src = './img/dog.jpg';
}
buf = [];
if (event.clipboardData) {
output('event');
for (const x of event.clipboardData.types) {
output(x);
}
for (const x of event.clipboardData.files) {
output(x.type);
if (x.type === 'image/png') {
const u = URL.createObjectURL(x);
buf.push(u);
document.querySelector('body > img').src = u;
}
}
} else if (window.clipboardData) {
output('window');
for (const x of window.clipboardData.types) {
output(x);
}
}
});
</script>
</body>
</html>
そういや<input type="file">;のfilesの中身は分離して保持できるらしい
html部
<div id="xyz">
<button>load</button>
<input type="file" accept="image/*">
<img width="100" height="100" style="border: 5px dotted yellow;" src="./img/dog.jpg">
<img width="100" height="100" style="border: 5px dotted yellow;" src="./img/dog.jpg">
<img width="100" height="100" style="border: 5px dotted yellow;" src="./img/dog.jpg">
</div>
js部
let files = [];
document.querySelector('#xyz > button')
.addEventListener('click', () => {
const imgs = document.querySelectorAll('#xyz > img');
for (let i = 0; i < files.length; i++) {
imgs[i].src = './img/dog.jpg';
URL.revokeObjectURL(files[i].url);
}
if (files.length === 3) {
files = [];
}
console.log('hoge');
document.querySelector('#xyz > input').click();
});
document.querySelector('#xyz > input')
.addEventListener('change', () => {
const imgs = document.querySelectorAll('#xyz > img');
for (const f of document.querySelector("#xyz > input").files) {
let obj = {};
obj.url = "";
obj.file = f;
files.push(obj);
}
for (let i = 0; i < files.length; i++) {
const k = files.length - i - 1;
const url = URL.createObjectURL(files[k].file);
files[k].url = url;
imgs[i].src = url;
}
});
それとクリップボードのfilesを<input type="file">のfilesにぶっこむこともできた
(ぶっこんだ後のfilesのオブジェクトがどういう取り扱いされるかは未確認)
(この場合、onchangeイベントは発生しない・・・?)
document.querySelector('body > textarea')
.addEventListener('paste', event => {
if (event.clipboardData) {
document.querySelector('#xyz > input').files = event.clipboardData.files;
}
});
onchange発生させるにはdispatchEventさせる?
document.querySelector('#xyz > input').dispatchEvent(new Event('change'));