ドラッグ&ドロップでファイルを選択する方法と画像ファイルのプレビュー

ドラッグ&ドロップでのファイル選択と画像プレビュー方法

フォームからアップロードするファイルを、画面外からのドラッグ&ドロップで選択可能にする方法と
ドラッグ&ドロップした画像ファイルをプレビューする方法を順番にメモします。

環境:
Mac OS 10.13.6、
ブラウザ : Google Chrome : 79.0.3945.88(Official Build) (64 ビット)

ドラッグ&ドロップしたファイルを選択状態にする

ブラウザへのドラッグ&ドロップ操作時に発生するイベント(DragEvent)の、
dropイベントを利用してinputタグへの選択を可能にします。

DragEventと発生タイミング

dragenter : 有効なドロップ先へドラッグ操作が開始したとき
dragover : 有効なドロップ先の上にドラッグされている間
dragleave : 有効なドロップ先からドラッグ操作が離れたとき
drop : 有効なドロップ先へドロップされたとき
(詳細)DragEvent

(HTML)

<form action="(送信先)" enctype="multipart/form-data" method="post">
  <input type="file" name="upfile">
</form>
<div id="preview-area">drop Here</div>

(CSS)

#preview-area {
  width: 200px;
  height: 200px;
  border: 1px dotted;
  object-fit: cover;
  background-color: #fff;
}

inputタグ、type属性をfileとしてファイルを選択出来るようにし、
ファイルをドラッグ&ドロップする領域を作成します。(div#preview-area )

(JavaScript)

document.addEventListener('dragover',function(e){
  e.preventDefault();
});
document.addEventListener('drop',function(e){
  e.preventDefault();
});

var target = document.getElementById('preview-area');

target.addEventListener('drop', function (e) {
  document.querySelector("[name='upfile']").files =     
  e.dataTransfer.files;
});

対象の領域以外でドラッグ&ドロップした際にファイルがブラウザ上で開かないよう、
document要素のdragoverとdorpイベントでpreventDefault関数を実行させる。
(イベント処理無効化)

対象の領域のdropイベントで、
ファイルを選択するinputタグのfilesプロパティへ※DataTransferオブジェクトのfilesの値を指定する事で、
通常のファイル選択と同じ動きとなる。

※ドラッグ&ドロップ操作の実行中、データを保持するために使われるHTML5の機能

ドラッグ&ドロップした画像をプレビューする

ドラッグ&ドロップで選択した画像ファイルを画面上にプレビュー出来るようにします。

今回はドラッグ&ドロップする場所とプレビューされる場所を同じ領域にしています。
(imgタグで作成した枠内へドラッグ&ドロップ)

(HTML)

<form action="(送信先)" enctype="multipart/form-data" method="post">
  <input type="file" name="upfile">
</form>        
<img id="preview-area">

(CSS)

#preview-area {
  width: 200px;
  height: 200px;
  border: 1px dotted;
  object-fit: cover;
  background-color: #fff;
}

(JavaScript)

document.addEventListener('dragover',function(e){
  e.preventDefault();
});
document.addEventListener('drop',function(e){
  e.preventDefault();
});

var target = document.getElementById('preview-area');

target.addEventListener('drop', function (e) {
  document.querySelector("[name='upfile']").files =     
  e.dataTransfer.files;
  
  //以降追加分
  var reader = new FileReader();

  reader.onload = function (e) {
    target.src = e.target.result;
  }
  reader.readAsDataURL(e.dataTransfer.files[0]);

});

dropイベント内で、FileReaderオブジェクトを使用する。

プレビュー用のimgタグのsrc属性に選択中のバイナリデータ(画像)を指定し、
readAsDataURLで読み込ませる事でプレビューが可能となります。

jQueryで記述する


(jQuery : 3.3.1)

jQueryを使用する場合、以下のように記述出来ます。

(注意)
jQueryはJavaScriptのイベントオブジェクトdataTransferに直接アクセス出来ませんので、
originalEvent.dataTransferと記述します。

$(document).on("dragover drop", function(e){
  e.preventDefault();
});

var target = $("#preview-area");

target.on("drop", function(e){

    $("[name='upfile']").prop('files', e.originalEvent.dataTransfer.files); 

    var reader = new FileReader();

    reader.onload = function (e) {
      target.attr('src', e.target.result);
    }
    reader.readAsDataURL(e.originalEvent.dataTransfer.files[0]);
    
});

参考:
MDN web docs / DragEvent
MDN web docs / Event.target
MDN web docs / DataTransfer
MDN web docs / FileReader.readAsDataURL()
ドラッグ&ドロップでファイルをアップロードする(最低限版)
jQuery Event から DOM Event を取る

Follow me!