0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【HTML/React】ユーザーがアップロードした画像をリサイズする

Last updated at Posted at 2025-05-10

背景

ユーザーがアップロードした画像をそのままレンダリングすると大きすぎるファイルだとこんな感じになる。
image.png
↑デカすぎんだろ.

コード

    function resizeImg(file, maxWidth, maxHeight) {
        return new Promise((resolve) => {
            const img = new Image();
            const fileurl = URL.createObjectURL(file);
            img.src = fileurl;
            console.log(fileurl)

            img.onload = () => {
             // 比率を保ってリサイズサイズを決定
            const originalWidth = img.width;
            const originalHeight = img.height;
            const ratio = Math.min(maxWidth / originalWidth, maxHeight / originalHeight);
            const newWidth = Math.round(originalWidth * ratio);
            const newHeight = Math.round(originalHeight * ratio);

            const canvas = document.createElement("canvas");
            const context = canvas.getContext("2d");
            if (!context) {
                URL.revokeObjectURL(fileurl);
                resolve(null);
            }
            canvas.width = newWidth;
            canvas.height = newHeight;
            context.drawImage(img, 0, 0, newWidth, newHeight);
            canvas.toBlob((blob) => {
                URL.revokeObjectURL(fileurl);
                resolve(blob); 
            }, file.type);
            };
            img.onerror = () => {
            URL.revokeObjectURL(fileurl);
            resolve(null); 
            };
        });
        }

imgの部分

const img = new Image(); //<img>タグを作成
img.src // 画像の読み込み用URL指定
img.onload // 画像の読み込みが成功したときに関数を実行
img.onerror // 読み込み時にエラーが発生したときに関数を実行

canvasの部分

const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");

canvasとは?
画像を描画する仮想のキャンバス要素で画面には描画されない

getContext("2d")で「2d描画のコンテキストを取得」

canvas.width = width;
canvas.height = height;
context.drawImage(img, 0, 0, width, height);

引数に受け取ったピクセルでキャンバスの縦横を指定します。

drawImage(img, 0, 0, width, height)はキャンパスへ、画像を張り付ける関数

canvas.toBlob((blob) => {
  URL.revokeObjectURL(objectUrl); // メモリ解放
  resolve(blob); //Promiseにblobの結果を返す
}, file.type);

今回はPromiseの成功結果としてblobを返している。

canvas.toBlobの処理の流れは下記。

第二引数で指定されたfile.typeでキャンバスの描画データをblobへと変換

変換データが第一引数(コールバック関数)に渡されて実行される

URL.revokeObjectURL(objectUrl);の意味

メモリ上にアクセス用の画像データが一時的に展開されているが、これはブラウザを閉じるまで保持されてしまう。
そのため、明示的にコード側で閉じる必要性がある。

URL.revokeObjectURL関数でメモリデータアクセス用のurlを指定することで削除可能

受け取ったblobをファイルオブジェクトにする

const fileblob = await resizeImg(FileData, 400,600);
var resizedFile = new File([fileblob], FileData.name, { type: FileData.type });

このresizedFileをimgタグのsrcに渡すと良い。

実際にテスト

(html部分などについては割愛)

const fileblob = await resizeImg(FileData, 400,600);

image.png
↑サイズがコンパクトになった。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?