HTML5/JavaScript でファイルのドラッグ&ドロップ、画像ファイルのプレビュー
はじめに
HTML5/JavaScript でファイルのドラッグ&ドロップ、画像ファイルのプレビューの実装方法。
TL;DR
- ドラッグ&ドロップ 使いたい場合は、
dragover
,drop
に対してpreventDefault()
が必要 dataTransfer.dropEffect
をcopy
に設定することで、ファイルドロップ時にファイルを参照できる- ドロップされたファイルは
drop
内でevent.dataTransfer.files
で参照可能 - ドラッグ中の UI 変更は
dragover
,dragleave
,drop
イベント内で実施 - 画像プレビューは
FileReader
のreadAsDataURL
を使う - 1つの
input
に 1つのファイルにするために、DataTransfer
を生成して、DataTranfer.items
のadd
を利用
目次
環境・条件
以下環境で確認
- MacOS Catalina v10.15.7(19H2)
- Chrome バージョン: 86.0.4240.111(Official Build)(x86_64)
詳細
参考:
- HTML5でファイルをドラッグして読み込むやつ - Qiita
- FileListは作れる!~file inputの中身も自由自在~ - Qiita
- javascript - How to set file input value when dropping file on page? - Stack Overflow
やりたいこと
- 複数の画像ファイルを POST したい
- 画像ファイルの設定方法1: ドラッグ&ドロップ
- 画像ファイルの設定方法2: ドラッグ&ドロップ 領域のクリック (ファイル選択ダイアログ開く)
- 画像ファイルの設定方法3: ファイル選択ボタンのクリック (ファイル選択ダイアログ開く)
- (諸事情で)ファイル選択やドラッグ&ドロップは1ファイルずつに制限
完成イメージ
簡素化のために <form method="POST" enctype="multipart/form-data">
は省略。
CodePen で見ないとドラッグ&ドロップ上手く動かないかも。
See the Pen [HTML/JS] ドラッグ&ドロップ ファイル読み込み by 17num (@17num) on CodePen.
HTML
1 | <div id="drag-and-drop-area"> |
SCSS(CSS)
1 | #drag-and-drop-area { |
JS
1 | // ファイル選択ボタン, ドラッグ&ドロップ領域のクリックでファイル選択ダイアログ |
ざっくり解説
ポイント箇所のみ簡単にまとめ。基本的には参考ページに書かれている通り。
- ドラッグ&ドロップ 使いたい場合は、
dragover
,drop
に対してpreventDefault()
が必要- 無いと別タブでファイルが開くなど、ブラウザ標準イベントが発火するため
dataTransfer.dropEffect
をcopy
に設定することで、ファイルドロップ時にファイルを参照できる- これは理解が浅いので間違ってるかも
- ドロップされたファイルは
drop
内でevent.dataTransfer.files
で参照可能 - 画像プレビューは
FileReader
のreadAsDataURL
を使う- FileReader 利用例: Vue で FileReader を使って画像のプレビュー表示
- ドラッグ中の UI 変更(色変えるとか) は
dragover
イベント内で実施 - 1つの
input
に 1つのファイルにするために、DataTransfer
を生成して、DataTranfer.items
のadd
を利用- 複数ファイルドロップされたものをそのまま
input.files = event.dataTransfer.files
とすると複数ファイル選択された状態になる
- 複数ファイルドロップされたものをそのまま
- クリック時のファイル入力にも対応するために
<input type="file">
も設置- ボタンなどクリック → file 入力フィールドクリック → 選択ダイアログ開く の流れ
- ファイル選択後、プレビューとともに新規
input
が生成されるので、元々設置していた方はvalue
,files
をクリア (<form>
での送信対象から削るため)
その他・メモ
特殊な要件が無ければ既存ライブラリを使うのも手。今回は要件がややこしく、ライブラリで実現できるのか不明(調査に時間かかる)だったので、ガッツリ自作した感じ。
- 10 Best Drag And Drop JavaScript Libraries (2020 Update) - CSS Script
- Dropzone.js
- interact.js - JavaScript drag and drop, resizing and multi-touch gestures for modern browsers
- Draggable JS – JavaScript drag and drop library
- etc…
まとめ
- ドラッグ&ドロップ 使いたい場合は、
dragover
,drop
に対してpreventDefault()
が必要 dataTransfer.dropEffect
をcopy
に設定することで、ファイルドロップ時にファイルを参照できる- ドロップされたファイルは
drop
内でevent.dataTransfer.files
で参照可能 - ドラッグ中の UI 変更は
dragover
,dragleave
,drop
イベント内で実施 - 画像プレビューは
FileReader
のreadAsDataURL
を使う - 1つの
input
に 1つのファイルにするために、DataTransfer
を生成して、DataTranfer.items
のadd
を利用
参考文献
- HTML5でファイルをドラッグして読み込むやつ - Qiita
- FileListは作れる!~file inputの中身も自由自在~ - Qiita
- javascript - How to set file input value when dropping file on page? - Stack Overflow
- javascript - How do I remove a file from the FileList - Stack Overflow
- HTML ドラッグ&ドロップ API - Web API | MDN
- Document: dragover イベント - Web API | MDN
- Document: dragleave イベント - Web API | MDN
- Document: drop イベント - Web API | MDN
- Event.preventDefault() - Web API | MDN
- FileReader - Web API | MDN
- FileReader.readAsDataURL() - Web API | MDN
- DataTransfer - Web API | MDN
- DataTransfer.files - Web API | MDN
- DataTransfer.items - Web API | MDN
- DataTransferItemList.add() - Web API | MDN
- FileList - Web API | MDN
関連記事
- jQuery Select2 で、初期値の設定と選択状態のクリア
- JavaScript で画像をローカルにダウンロード
- JavaScript で複数画像を zip に圧縮してローカルにダウンロード
- HTML img タグで画像が 404 エラーのときに代替画像を表示する方法
- mailto リンクで 宛先/CC/BCC/件名/本文 を指定 (JavaScript サンプルあり)
- Chart.js(vue-chartjs) でツールチップの表示内容を変更
- JavaScript で URL のクエリパラメータを操作する方法
- axios で添付ファイルありのリクエスト(multipart/form-data の POST)