【Vue.js】ドラッグ&ドロップでファイルアップロード機能を実装(プレビュー付き)

開発環境

  • vue@2.x
  • vuetify@2.x

実装イメージ

1.初期画面

2.ドラッグ中

3.ドロップ時

ドラッグ&ドロップを開始した際にデザインを変更したり、ドロップされたファイルの情報を表示したり、アップしたファイルをプレビューできるように実装をしていきます。CSSの記述を最低限にするため、Vuetifyを使用しております。

コード解説

コードの中でやっていることは下記の3つです。それぞれ解説を行います。

  • ドラッグ中にデザインを変更
  • アップロードするファイルデータを取得
  • プレビュー用にファイルの中身を表示する

HTML

<div id="app">
  <v-app>
    <v-container>
      <v-row class="pa-6">
        <div
          class="drag-area"
          @dragenter="drag = true"
          @dragover.prevent="drag = true"
          @drop.prevent="drop"
          @dragleave="dragleave()"
          :class="{ enter: drag }"
        >
          <div class="drag-title">ドラッグ&ドロップ</div>
        </div>
        <div class="drag-result pl-4">
          <div>ファイル名 : {{ file.name }}</div>
          <div>ファイルタイプ : {{ file.type }}</div>
          <div>ファイスサイズ : {{ file.size }}</div>
          <div>プレビュー : <br>
            <img 
              v-show="file.preview" 
              :src="file.preview"
              style="width:150px;"
            >
          </div>
        </div>
       </v-row>
     </v-container>
  </v-app>
</div>

今回のドラッグ&ドロップ機能を実装するにあたり、使用したイベントは下記の4つです。

  • @dragenter
  • @dragover.prevent
  • @drop.prevent
  • @dragleave

drop以外のイベントは、ドラッグエリアのスタイル変更のために使用します。dragenterはドラッグエリアにマウスが入ったタイミング、dragoverはドラッグエリアにマウスが乗っている間、そしてdragleaveはドラッグエリアからマウスが外れたタイミングで発火します。つまり、dragenter、dragoverのイベントが発火している間はclass=”enter”が付与されます。:class=”{ enter: drag }”でクラスバイディングを行います。

CSS

ドラッグ&ドロップを実装している際に、ドラッグエリアのスタイルを変更するよう記述しています。class=”enter”が付与された際には、枠線と背景色を変更しています。(上記「実装イメージ」> 「2. ドラッグ中」)

.drag-area{
  min-height: 200px;
  max-width: 500px;
  width: 100%;
  border: 2px dashed;
  display: flex;
  align-items: center;
  justify-content: center;
}
.enter.drag-area {
  border: 2px dashed #1867c0;
  background: #d4e8ff;
}

Vue.js

Vue.jsのコード解説では、主に下記の2つの処理について解説します。

  • アップロードするファイルデータを取得
  • プレビュー用にファイルの中身を表示する
new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    drag: false,
    file: {
      name: "",
      type: "",
      size: "",
      preview: ""
    }
  },
  methods: {
    drop(event) {
      this.drag = false
      const files = event.dataTransfer.files
      this.file.name = files[0].name
      this.file.type = files[0].type
      this.file.size = files[0].size
      
      const reader = new FileReader()
      reader.onload = event => {
        this.file.preview = event.target.result
      }
      reader.readAsDataURL(files[0])
    },
    dragleave() {
      this.drag = false
      this.files = []
    }
  }
})

アップロードするファイルデータを取得

ドラッグ&ドロップでファイルをアップロードする場合、event.dataTransfer.filesでファイルサイズ、ファイル名、ファイルタイプなどのオブジェクトを取得できます。小ネタですが、Vue.jsの場合HTMLに記載しているメソッドの引数にeやeventを書かなくても、eventを取得できます。

取得したファイルオブジェクトから、name、type、sizeをそれぞれ取得すればアップロードしたファイルの情報を表示させることができます。

プレビュー用にファイルの中身を表示する

ファイルアップロード機能を実装する際に、プレビュー機能があるとサーバーに送信する前にアップロードするファイルを確認できるので便利です。

該当の処理は下記。

const reader = new FileReader()
reader.onload = event => {
  this.file.preview = event.target.result
}
reader.readAsDataURL(files[0])

const reader = new FileReader()

FileReader オブジェクトを使用すると、Web アプリケーションは、ユーザーのコンピュータに保存されているファイル (または生データ バッファ) の内容を非同期に読み取ることができます。File または Blob オブジェクトを使用して、読み込むファイルまたはデータを指定します。

FileReaderオブジェクトについて

reader.readAsDataURL()

readAsDataURL メソッドは、指定されたBlob または File の内容を読み込むために使用されます。読み込み操作が終了すると、readyState が DONE となり、loadend (en-US) が発生します。このとき、result 属性には、ファイルのデータを表す、base64 エンコーディングされた data: URL の文字列が格納されます。

readAsDataURL メソッド

一応、CodePen

See the Pen ドラッグ&ドロップ by waibandl321 (@JumCode) on CodePen.

もし不明な点や質問、ご指摘がありましたら、記事下のフォームからコメントをお願いします。

関連記事

コメント

この記事へのコメントはありません。