2020年12月21日 • ☕️ 3 min read

スマホが日進月歩の時代になりました。写真1枚で簡単に10Mbを超えるでしょう。サーバへ送信する前に、クライアント側でアップロードされたイメージをリサイズできれば、サーバに対する負荷を軽減できるし、アップロードスピードの向上するためユーザビリティ質にもつながります。なので、クライアントでのイメージリサイズは現代ウェブアプリケーションの必須機能ともいえるでしょう。

WebAPIを利用すれば、リサイズ自身は難しくありません。htmlのcanvas domからtoBlobでイメージのサイズと画質(quality)を調整するのが一般的です。

Copy
const canvasDom = document.createElement('canvas');
// quality → 0.9
const quality = 0.9;
// height, width → 50%
canvasDom.width = image.width / 2;
canvasDom.height = image.height / 2;

const ctx = canvasDom.getContext('2d');
ctx.drawImage(image, 0, 0, image.height / 2, image.width / 2);

canvasDom.toBlob(
  function blobCallback(blob) {
    uploadFile = new File([blob], "file-name.jpg");
  },
  type,
  quality,
);

しかし、アップロードされたFileからImageへ変換し、そして、変換されたImageをCanvas DOMに書き込めるかどうかはブラウザによって挙動が異なります。 自分がこれから紹介する3つの方法で検証してみました。

TLDR:動作がおかしいブラウザはiOSのSafariとMacOSのSafariでした。PCのChrome、FireFox、AndroidのChromeいずれもどの方法でも問題ありません。頑張って、Appleさん。

方法1:FileReader.readAsDataURL

Google先生に聞くと、この方法一番多いです。ただ、iOSとMacOS上にはとても不安定で、FileImageへ変換するとき、image.width0になる可能性があるので、おすすめできません。

使い方は簡単です。 ※Promiseでラップしたらcallback地獄を避けられます。

Copy
// fileは選択されたファイル

const image = new Image();
await new Promise((resolve) => {
  const reader = new FileReader();
  reader.onload = function (e) {
    image.src = e.target.result;
    resolve();
  };
  reader.readAsDataURL(file);
});

// imageを使う

方法2:createImageBitmap

これは一番簡単だが、Safariは完全にアウトですね。

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap#Browser_compatibility

Copy
// fileは選択されたファイル

const image = createImageBitmap(file);

// imageを使う

方法3:URL.createObjectURL

この方法は今の時点で一番安定しています。

Copy
// fileは選択されたファイル

// `file`をobjectURLへ変換
const url = URL.createObjectURL(file);

// imageへ変換
const image = new Image();
img.decoding = 'async';
img.src = url;
await new Promise((resolve, reject) => {
  img.onload = () => resolve();
  img.onerror = () => reject(Error('Image loading error.'));
});

// imageを使う

完了

3つの方法の検証用のウェブサイト:https://ios-resize-image.vercel.app/

ソースコード:https://github.com/thundermiracle/ios-resize-image


関連投稿

HEIFファイルのアップロード対策

2021年7月11日

Gatsbyをバージョンアップした後developモード起動できない問題

2020年5月10日

ThunderMiracle

Blog part of ThunderMiracle.com