【Vue 2】ドラッグ&ドロップで画像を読み込む
サンプル
ドラッグ&ドロップする場合は、別ウィンドウで表示してください。
解説
ドラッグ&ドロップ
<template>
<div class="image-input">
<div
class="image-input__field"
:class="{ over: isDragOver }"
@dragover.prevent="onDrag('over')"
@dragleave="onDrag('leave')"
@drop.stop="onDrop"
>
<input type="file" title @change="onChange" />
<p>画像をドラッグ&ドロップ <br />またはクリックでファイル選択</p>
</div>
</div>
</template>
ドラッグ&ドロップを実装するにあたり、使用するイベントはdragover
、dragleave
、drop
の 3 つです。
これらのイベントについては、こちらの記事を参考にしてください。
dragover
、dragleave
は見た目を変更するのに使用しています。
以下のように大した処理はしていません。
onDrag(type) {
this.isDragOver = type === "over";
},
drop
では、ドロップされたファイル情報を読み取ります。
ファイル情報は具体的に、イベントオブジェクトのdataTransfer
から取得します。
今回はドロップされたファイルが 1 つかつ画像の場合のみ読み取るようにしています。
onDrop(event) {
this.isDragOver = false;
const files = event.dataTransfer.files;
if (files.length !== 1 || files[0].type.indexOf("image") !== 0) {
return;
}
this.readImage(files[0]);
},
実装のポイントは、dragover
にprevent
修飾子を、drop
にstop
修飾子を付けることです。
dragover
にprevent
修飾子を付けることで、デフォルトの動作を抑制します。
これがなければdrop
は機能しません。
drop
にstop
修飾子を付与するのは、親へのイベントの伝搬を防ぐためです。
これがなければ親要素のdrop
イベントが発火し、エラーが出力されます。
ファイル選択
ファイルを選択するには以下のようにtype=file
のinput
を宣言します。
<input type="file" title @change="onChange" />
「ファイル選択」というボタンをクリックするとフォルダが開き、ファイルを選択するとchange
イベントが発火します。
change
では、drop
と同様にファイル情報を読み取る処理を行います。
ただし、ファイル情報はdataTransfer
ではなくtarget
から取得する点が異なります。
onChange(event) {
const files = event.target.files;
if (files.length !== 1 || files[0].type.indexOf("image") !== 0) {
return;
}
this.readImage(files[0]);
},
ファイル読み込み
readImage(file) {
let reader = new FileReader();
reader.onload = this.loadImage;
reader.readAsDataURL(file);
},
loadImage(e) {
let image = new Image();
image.src = e.target.result;
this.image = image;
}
ファイルの読み込みには、FileReader
(参照)を用います。
FileReader
のonload
は、ファイルの読み込みが成功した場合に発生するイベントになります。
ここではファイルの読み込み後にImage
要素を作成するようにしています。
あとはreadAsDataURL()
で対象のファイルを読み込みます。
画像の表示
img
シンプルに<img>
を使用して画像を表示します。
<img :src="image.src" />
Canvas
以下のように Canvas を使用して表示することもできます。 Canvas についてはあまり詳しくないので、詳細は割愛します。
<template>
<!-- -->
<canvas id="canvas"></canvas>
<!-- -->
</template>
<script>
//...
methods: {
//...
draw() {
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
canvas.width = this.image.width;
canvas.height = this.image.height;
context.drawImage(this.image, 0, 0);
}
//...
}
</script>