1. ホーム
  2. Web制作
  3. html5

html5 canvasによる画像圧縮のサンプルコード

2022-02-01 16:13:52

私は画像のbase64が大きすぎる場合、要求は非常に遅く、深刻な直接タイムアウトになることがわかったので、私はアップロードする前に画像を圧縮することを考え、その後大幅に効率を改善することができますバックグラウンドにアップロードし、ここでいくつかのピットを記録するキャンバス圧縮画像を使用して発生しました。完全なコードは、この記事の最後に与えられます。

最初の落とし穴は、圧縮する際に画像自体の幅と高さを取得せず、600*480の固定幅と固定高さを与えてしまったことです。アバターを修正した際、テスト時にアップロードした画像が小さい画像だったため、圧縮した画像が不完全でほとんど空白になってしまったことが問題で、これは圧縮時に画像の元の幅と高さを考慮していないためです。

2つ目の落とし穴は、1つ目の落とし穴の解決策として、画像が読み込まれた後に(onload)幅と高さを取得してcanvasに代入する方法がありますが、これには画像が非同期に読み込まれるという落とし穴があり、リターン時に、必要な圧縮Base64ではなく未定義が返ってくる可能性があります。ここでの解決策は、新しい Promise を作成し、その結果を resolve() として返し、結果を取得するときに .then() を呼び出すことです。

ナレッジポイント

  • canvasのtoDataURL('image/png', 0.9) ; キャンバス画像をbase64に変換します。第1パラメータは画像のタイプ、第2パラメータは画像の解像度を指定します。
  • 最大サイズを指定し、画像自体がこのサイズより大きい場合は、最大側をスケーリングし、もう一方を画像のスケーリングに従って設定し、キャンバスに設定する .

miniImage.js

export default async function miniSize(imgData, maxSize = 200*1024){
    // const maxSize = 200 * 1024;

    if(imgData && imgData.files && imgData.files.size < maxSize) {
        return imgData.url;
    }else{
      console.log('---------------- compressed image -------------------');
      const canvas = document.createElement('canvas');
      let img = new Image();
      img.src = imgData.url;
      let ctx = canvas.getContext('2d');
      return new Promise((resolve =>{
        img.addEventListener('load', function(){
          // the original size of the image
          let originWidth = this.width;
          let originHeight = this.height;
          // maximum size limit
          let maxWidth = 400, maxHeight = 400;
          // target size
          let targetWidth = originWidth, targetHeight = originHeight;
          // the image size exceeds the 400x400 limit
          if (originWidth > maxWidth || originHeight > maxHeight) {
            if (originWidth / originHeight > maxWidth / maxHeight) {
              // wider, size by width
              targetWidth = maxWidth;
              targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
              targetHeight = maxHeight;
              targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
          }
          canvas.width = targetWidth;
          canvas.height = targetHeight;
          ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
          let base64 = canvas.toDataURL('image/png', 0.9);
          resolve(base64);
        }, false);
      }))
    }
}



呼び出し中。

test.js

onChangeImg = async (files, type, index) => {
    let previous = this.props.imagePicker.files;
    if(type === "add") {
      let result = miniSize(files[files.length-1]);
      // use the .then() call to get the result
      await result.then(res => {
         previous.push({url: res});
      });
    }else if(type === "remove") {
        previous.splice(index,1);
    }
    await this.props.dispatch({
      type: 'imagePicker/saveImage',
      payload: {
        files: previous
      }
    })
  }


以上、本記事の全内容をご紹介しましたが、皆様の学習のお役に立てれば幸いです。また、Script Houseをより一層応援していただければ幸いです。