usakdsteen

ゆうさくですてぃーん

ぶらうざ:「くりっぷぼーど」からの貼付

ツイッターのツイートとかで画像をクリップボードから貼り付けられたけど

雑に(MDN内で検索で)やりかた調べた

 

雑すぎて最初に辿りついたのは

ClipboardAPIなるもので、これパーミッションが必要とかで、何か違うなーって…

クリップボード API - Web API | MDN

ためしに実行してみたらパーミッション求められて、ツイッターとかでそんなの無かったと、コレ違うと

 

もうちょっと調べてみたら

普通に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'));