🌟

クライアント側で画像をcanvasで最大サイズ以下にリサイズ

2022/09/03に公開

・最大サイズ以下になるようにcanvasで画像をリサイズする
・サンプルコードで一連の流れがまとまっているものが見当たらないためメモ

各処理を分割したメソッド

const readAsDataURL = (imgFile) => {
  return new Promise((resolve) => {
    const fileReader = new FileReader();
    fileReader.onload = () => {
      resolve(fileReader.result);
    };
    fileReader.readAsDataURL(imgFile);
  });
};

const loadImage = (src) => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = (e) => reject(e);
    img.src = src;
  });
};

const getScale = (width, height, maxSize = 1280) => {
  const size = Math.max(width, height);

  // 最大サイズ以下は1
  if (size <= maxSize) {
    return 1;
  }

  // 小数第4位で四捨五入する
  const scale = maxSize / size;
  return Math.round(scale * 10000) / 10000;
};

const resizeImgDataUrl = (img, scale) => {
  const canvas = document.createElement('canvas');
  canvas.width = img.width * scale;
  canvas.height = img.height * scale;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0, img.width * scale, img.height * scale);
  // jpgの品質はデフォルト値の「0.92」とする
  return canvas.toDataURL('image/jpeg');
};

使い方

// FileReaderでdataurlとして読み込み
/** @type {File} */
const inputFile = ... // input type="file"などから取得
const inputImgDataUrl = await readAsDataURL(inputFile);

// img属性で画像を読み込み
const inputImg = await loadImage(inputImgDataUrl);

// 縮小するscaleを取得
const scale = getScale(inputImg.width, inputImg.height);

// outputImgDataUrlがリサイズ後のdataurl
const outputImgDataUrl = resizeImgDataUrl(inputImg, scale);

Discussion