🖼
<input type="file">で選択した画像を表示する
概要
<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などで見るような「白とグレーの市松模様」にするのもあり?🤔
参考
- <input type="file"> - HTML: HyperText Markup Language | MDN
- FileReader - Web API | MDN
- URL.createObjectURL() - Web API | MDN
- EventTarget.addEventListener() - Web API | MDN
- Web アプリケーションからのファイルの使用 - Web API | MDN
- object-fit - CSS: カスケーディングスタイルシート | MDN
- object-position - CSS: カスケーディングスタイルシート | MDN
- Blob(現代の JavaScript チュートリアル)
Discussion