今回は、JavaScript を使って、ブラウザにドラッグ&ドロップされた画像を Base64 形式にエンコードし、<img>タグで表示する方法をご紹介します。

ドラッグ&ドロップされた画像をBase64 エンコードして表示させるサンプル

まずは、実際に動作するサンプルをご紹介します。ドロップエリアに画像ファイルをドロップすると、JavaScript によって Base64 エンコードされた Data URL 形式の画像が表示されます。この処理はすべてブラウザ内で完結し、サーバとの通信は発生しません。

See the Pen Drag&Drop images in Base64 format by YUTSUZO (@YUTSUZO) on CodePen.

コードの説明

HTML

HTML はドロップエリアと画像を表示させるエリアがあるだけのシンプルなものです。

<div id="dropArea" class="drop-area">ここにドロップ!</div>
<div id="imageList" class="image-list"></div>

JavaScript

次に、JavaScript の説明です。まず、コード全体はこのようになっています。

// ドラッグ&ドロップ時のイベントリスナー登録
window.addEventListener("DOMContentLoaded", function () {
  document.getElementById("dropArea").addEventListener("dragover", dropAreaDragOver);
  document.getElementById("dropArea").addEventListener("drop", dropAreaDrop);
});

// ブラウザにドラッグされた時の処理
function dropAreaDragOver(event) {
  // デフォルトの動作をキャンセル
  event.preventDefault();

  // マウスカーソルの表示を変更
  event.dataTransfer.dropEffect = "copy";
}

// ドロップエリアにドロップされた時の処理
function dropAreaDrop(event) {
  // デフォルトの動作をキャンセル
  event.preventDefault();

  // ドロップされたファイルを取得
  var files = event.dataTransfer.files;

  // ドロップされたファイルの処理
  for(var i = 0; i < files.length; i++) {
    setDataURL(event.dataTransfer.files[i]);
  }
}

// ファイルの処理
function setDataURL(file) {
  if (!file.name.match(".(jpeg|jpg|png|bmp|gif|webp)$")) {
    alert('JPG, PNG, BMP, GIF, WEBP 形式のファイルをアップロードしてください');
    return false;
  }

  // FileReader オブジェクトを生成
  var reader = new FileReader();

  // ファイル読み込み時のイベント
  reader.addEventListener("load", function(event) {
    var data = event.currentTarget.result;

    // IMG タグの生成
    var img = document.createElement("img");
    img.src = data;
    document.getElementById("imageList").appendChild(img);
  });

  // ファイルを DataURL 形式で読み込み
  reader.readAsDataURL(file);
}

ここからは、このコードについて、いくつかに分けて説明していきます。

ドラッグ&ドロップ時のイベントリスナー登録

この部分では、ブラウザにファイルがドラッグされた時と、ドロップエリアにドロップされた時に処理を行う関数を登録しています。

// ドラッグ&ドロップ時のイベントリスナー登録
window.addEventListener("DOMContentLoaded", function () {
  document.getElementById("dropArea").addEventListener("dragover", dropAreaDragOver);
  document.getElementById("dropArea").addEventListener("drop", dropAreaDrop);
});

ファイルがブラウザにドラッグされた時の処理

ファイルがブラウザにドラッグされた時に処理を行う関数の説明です。

// ブラウザにドラッグされた時の処理
function dropAreaDragOver(event) {
  // デフォルトの動作をキャンセル
  event.preventDefault();

  // マウスカーソルの表示を変更
  event.dataTransfer.dropEffect = "copy";
}

この部分では、まず、event.preventDefault();でブラウザのデフォルトの処理をキャンセルしています。これが無いと、ドラッグされた画像がそのままブラウザで開かれるだけになってしまいます。

event.dataTransfer.dropEffect = "copy";は、ドラッグ中にマウスカーソルに表示される文言を変更するためのものです。

ファイルがドロップエリアにドロップされた時の処理

ファイルがドロップエリアにドロップされた時に処理を行う関数の説明です。

// ドロップエリアにドロップされた時の処理
function dropAreaDrop(event) {
  // デフォルトの動作をキャンセル
  event.preventDefault();

  // ドロップされたファイルを取得
  var files = event.dataTransfer.files;

  // ドロップされたファイルの処理
  for(var i = 0; i < files.length; i++) {
    setDataURL(event.dataTransfer.files[i]);
  }
}

この部分でも、ドラッグ時の関数と同じくブラウザのデフォルトの処理をキャンセルしています。そして、ドロップされたファイルを取得し、ファイル数の分だけファイル処理用の関数を実行しています。

ドロップされたファイルの処理

そして、今回のキモとなる、ファイルの処理部分です。

// ファイルの処理
function setDataURL(file) {
  if (!file.name.match(".(jpeg|jpg|png|bmp|gif|webp)$")) {
    alert('JPG, PNG, BMP, GIF, WEBP 形式のファイルをアップロードしてください');
    return false;
  }

  // FileReader オブジェクトを生成
  var reader = new FileReader();

  // ファイル読み込み時のイベント
  reader.addEventListener("load", function(event) {
    var data = event.currentTarget.result;

    // IMG タグの生成
    var img = document.createElement("img");
    img.src = data;
    document.getElementById("imageList").appendChild(img);
  });

  // ファイルを DataURL 形式で読み込み
  reader.readAsDataURL(file);
}

まず、ファイルが画像ファイルであるかチェックを行っています(今回この部分はそれほど重要ではありませんが)。

次に、ファイルを読み込むための FileReader オブジェクトを生成しています。そして、FileReader オブジェクトに対してファイル読み込み時のコールバック関数を登録し、その後、readAsDataURL()メソッドを使用してファイルを読み込むという流れになっています。

この、readAsDataURL()メソッドは、data:から始まる Data URL 形式でファイルを読み込んでくれるため、特別なことをしなくても<img>タグのsrc属性にそのまま入れてあげるだけで画像として表示されるようになります。

終わりに

やる前は結構難しい処理かと思っていましたが、実際にやってみると意外と少ないコードで出来てしまったので驚きました。今回紹介したコードを使用して作った「LINE着せかえシミュレータ」も、よかったら是非お試しください!