画像アップロード機能を実装するときによく使うのでメモします。
/**
* @param {HTMLImageElement} imgEL
* @param {Number} maxSize
* @return {Promise<Blob>}
*/
const resizeImage = (imgEL, maxSize, type = 'image/png') =>
new Promise((resolve) => {
const ratio = imgEL.naturalWidth / imgEL.naturalHeight
const canvas = document.createElement('canvas')
canvas.width = ratio >= 1 ? maxSize : maxSize / ratio
canvas.height = ratio < 1 ? maxSize : maxSize / ratio
canvas.getContext('2d').drawImage(imgEL, 0, 0, canvas.width, canvas.height)
canvas.toBlob(resolve, type)
})
戻り値のBlobが縮小されたやつでそのままサーバにアップロードすればいい感じですね。
使用例
<body>
<input type="file">
<div id="preview"></div>
<button>アップロード</button>
<script>
const resizeImage = (imgEL, maxSize, type = 'image/png') =>
new Promise(resolve => {
const ratio = imgEL.naturalWidth / imgEL.naturalHeight
const canvas = document.createElement('canvas')
canvas.width = ratio >= 1 ? maxSize : maxSize / ratio
canvas.height = ratio < 1 ? maxSize : maxSize / ratio
canvas.getContext('2d').drawImage(imgEL, 0, 0, canvas.width, canvas.height)
canvas.toBlob(resolve, type)
})
const pFileReader = blob =>
new Promise(resolve => {
const fr = new FileReader()
fr.readAsDataURL(blob)
fr.onload = e => resolve(e.target.result)
})
const pImage = src =>
new Promise(resolve => {
const img = new Image()
img.src = src
img.onload = e => resolve(img)
})
document.querySelector('input').onchange = async e => {
const file = e.target.files[0]
const preview = document.querySelector('#preview')
const src = await pFileReader(file)
const img = await pImage(src)
// 本当に縮小されることを確認したい場合は以下をコメントアウト
// const blob = await resizeImage(img, 100, file.type)
// img.src = await pFileReader(blob)
preview.appendChild(img)
}
document.querySelector('button').onclick = async () => {
const file = document.querySelector('input').files[0]
const src = await pFileReader(file)
const img = await pImage(src)
const blob = await resizeImage(img, 100, file.type)
// blobをアップロード ~
}
</script>
</body>
以上!
FileReader使ってますけど, URL.createObjURLで代用できますよ。