画像のリサイズ処理(縮小)を簡単に実装する/Javascript/Vue.js

投稿者: | 2019年4月21日

Vue.jsでユーザーからの画像投稿を作っていたのですが、「画像のリサイズ処理」をどうやって実装すればいいのか?について色々調べることになりました。ようやく動くようになったので、画像のリサイズ処理の実装方法についてまとめておきます。

はじめに

https://qiita.com/elastic/items/aef72b8803d70a25f468

本記事では、こちらのQiita記事で紹介いただいたコードをベースに、ちょっと加筆したものを紹介しています。

画像のリサイズ処理が必要な理由

  • スマホカメラで画質がよくなっており、画像の容量がバカにならない。

これに尽きると思います。スマホで写真撮ると、1枚2MB以上のファイルサイズになったりしますから。ユーザーが撮影した写真をそのままアップしてWebで公開してしまうと、ページ表示の遅延につながりSEO不利だったり、そもそもユーザーが使いにくいといった状態になってしまいます。また画像を置いておくストレージの容量や通信料もバカになりません。

画像のリサイズ処理はブラウザで行う

昔のWebシステムであれば、サーバーにいったんアップロードした後にサーバーサイドのプログラムで画像のサムネイルを作成する構成が一般的でした。

しかし、現在はブラウザの機能が強化されましたので、クライアントサイド(ブラウザ上)で画像のリサイズ処理が可能となっています。つまりJavascriptだけで画像のリサイズが可能です。

 

実装

仕様:

  • 元画像の縦‐横の比率は維持する
  • 元画像の縦、横の長い方を、maxSizeに合わせる(縦、横ともにmaxSize以下であればリサイズしない)
  • 短い方は比率を維持した状態で縮小する

リサイズ処理部分のコード

imageResize.js

const imageResize = {}
imageResize.resizeImage = (imgEL, maxSize, type = 'image/png') =>
new Promise(resolve => {
let w = imgEL.naturalWidth
let h = imgEL.naturalHeight
const canvas = document.createElement('canvas')
if (w >= h && w > maxSize) {
// 横が長い → 横の長さ:maxSize 縦の長さ:maxSize * h/w
canvas.width = maxSize
canvas.height = maxSize * h / w
} else if (w < h && h > maxSize) {
 // 縦が長い → 縦の長さ:maxSize 横の長さ:maxSize * w/h 
canvas.width = maxSize * w / h
canvas.height = maxSize
} else {
 // 縦、横ともにmaxSize以下→縮小しない
canvas.width = w
canvas.height = h
}
canvas.getContext('2d').drawImage(imgEL, 0, 0, canvas.width, canvas.height)
canvas.toBlob(resolve, type)
})
imageResize.pFileReader = blob =>
new Promise(resolve => {
const fr = new FileReader()
fr.readAsDataURL(blob)
fr.onload = e => resolve(e.target.result)
})
imageResize.pImage = src =>
new Promise(resolve => {
const img = new Image()
img.src = src
img.onload = e => resolve(img)
})
export default imageResize

Vue.jsのプロジェクトへの組込み方法

組込方は色々あると思うので、あくまで一例とお考えください。

①上記コード(imageResize.js)の配置

src/assets/js/imageResize.js

こちらのパスに格納しました。

②App.vueへの組込

<template>
<v-card flat>
<v-card-title class="title"><v-icon>edit</v-icon>投稿</v-card-title>
<v-container>
<v-layout row wrap class="rowWrap">
<v-flex xs12 style="text-align:left;">
<input type="file" style="display: none;" ref="image" v-on:change="onFileChange" mulitple="multiple">
<v-subheader style="height:10px;">画像登録</v-subheader>
<v-layout v-if="imageURI.length>0" style="margin-top:10px;max-width:450px;">
<v-flex xs4 v-for="(image,id) in imageURI" :key=id>
<img :src="image" style="max-width:90%;max-heght:300px;">
</v-flex>
</v-layout>
<p style="margin:10px 0;padding:0;">
<v-btn @click="pickImage()" flat outline round color="primary">
<v-icon>add photo</v-icon>画像を追加する
</v-btn>
</p>
</v-flex>
</v-layout>
<p style="text-align:center;margin:27px 0;">
<v-btn @click="onSend" dark block large color="primary">
<span><v-icon>send</v-icon>&nbsp;送信</span>
</v-btn>
</p>
</v-container>
</v-card>
</template>
<script>
import {db} from '../../main'
import firebase from 'firebase'
import imageResize from '../../assets/js/imageResize.js' // 読み込み
var fileExtensions = ['jpg', 'jpeg', 'png', 'bmp', 'gif']
const maxSize = 700
export default {
data () {
return {
isLoading: false,
imageData: [], // ストレージアップ用。Blob
imageURI: [] // アップロード確認用(画面表示用)。 URI
}
},
methods: {
pickImage () {
// 画像選択ダイヤログの表示
this.$refs.image.click()
},
async onFileChange (e) {
// ユーザーが画像選択したら呼ばれる
let files = e.target.files || e.dataTransfer.files
   // imageResize.jsの関数の利用
const src = await imageResize.pFileReader(files[0])
this.imageURI.push(src)
const img = await imageResize.pImage(src)
const blob = await imageResize.resizeImage(img, maxSize, 'image/png')
this.imageData.push(blob)
}
},
components: {
}
}
</script>
  1. <script>の先頭でimageResize.jsをimportします
  2. あとはメソッドの中で読み込んだ関数を呼べばOKです。※上記コードでは「onFileChange」の中でのみ利用しています。

さいごに

こんな感じで画像のリサイズが実装できました。

画像リサイズはユーザーにとってもメリットが大きいと思いますので、ぜひ実装してユーザビリティーを上げていきましょ~


カツオが開発したWebサービスです。

「セールサーチ」ネットショップのセール情報の検索サイト!

平成の想い出を気軽に年表にしてシェアすることができるサービスです。ぜひ使ってみてください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です