<input type="file">で選択した画像を表示する

公開:2020/10/03
更新:2020/10/04
3 min読了の目安(約3300字TECH技術記事

概要

<input type="file">で選択した画像を表示し、確認できるようにする。

実装

HTML

<div style="margin-bottom: 1em">
  <input id="input" type="file">
</div>
<div>
  <img id="img">
</div>

JavaScript

input要素のchangeイベントを拾って処理を行う。

document.querySelector('#input').addEventListener('change', (event) => {
  const file = event.target.files[0]

  // fileがundefinedの時にreader.readAsDataURL(file)がエラーになるため、
  // !fileがfalseの場合にreturnする。
  if (!file) return

  const reader = new FileReader()

  reader.onload = (event) => {
    document.querySelector('#img').src = event.target.result
  }

  reader.readAsDataURL(file)
})
async/await書き換えver
// Fileオブジェクトを受け取ってdataURLを返す
function load(file) {
  return new Promise((resolve) => {
    const reader = new FileReader()

    reader.onload = (event) => {
      resolve(event.target.result)
    }

    reader.readAsDataURL(file)
  })
}

// コールバック関数にasyncをつける
document.querySelector('#input').addEventListener('change', async (event) => {
  const file = event.target.files[0]

  if (!file) return

  const dataURL = await load(file)
  document.querySelector('#img').src = dataURL
})
FileReaderを使用せずblob(オブジェクトURL)書き換えver

FileからオブジェクトURLを生成する。

document.querySelector('#input').addEventListener('change', (event) => {
  const file = event.target.files[0]

  if (!file) return

  const img = document.querySelector('#img')

  // 既にURLが存在する場合は開放する。
  // (使い方によってはURLが作られるごとにメモリに溜まり続けるため)
  if (img.src) URL.revokeObjectURL(img.src)

  const url = URL.createObjectURL(file)
  img.src = url
})
【メモ】event.target以外からもfilesを拾える

addEventListenerで設定したコールバック関数のthisからfilesを取得できる。…が、氷砂糖の場合は実装の都合でアロー関数を多用するためあまり使いそうにない🤔(あとevent.targetから引っ張ってきた方が流れが分かりやすそうなのもある)

document.querySelector('#input').addEventListener('change', function (event) {
  console.log(this.files)
}

一応このような取り方も可能。

document.querySelector('#input').addEventListener('change', function () {
  console.log(document.querySelector('#input').files)
}

CSS

選択した画像を一定以下のサイズで表示するためCSSを追加した(JavaScriptで画像を加工する方法もあるが、今回はCSSで対応する)。

#img {
  width: 240px;
  height: 240px;
  object-fit: scale-down;
  background-color: #ddd;
}
  • object-fitを指定した画像の表示位置を調整したい場合は、object-positionを使用する(object-position: left top;など)。
  • 表現方法の一つとして、background-imageをPhotoshopなどで見るような「白とグレーの市松模様」にするのもあり?🤔

参考