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

キャンバスで画像を圧縮し、カードを作成する例

2022-02-01 09:33:57

イベントページなどをやっていると、画像をアップロードする必要があったり、生成したテキストとステッカーでカードを生成して、ユーザーが長押しして保存する必要があったりすることがよくあります。この要件は以前にも一度ありましたが、最近またそれに出会い、canvasを使って実現しました。単純にブログのアウトを整理する もし、もっと良い実装方法があれば、一緒に議論してください。

canvasで画像を圧縮する

htmlでwrite inputタグをtype fileで使用する場合、携帯電話のアルバムから利用可能な写真を取り出し、写真機能のカメラにも対応することができます。このシナリオでは、画像のサイズが大きくなり、バックエンドがサポートする最大範囲を超える可能性があり、その結果、アップロードに失敗することがあります。

<input id="file" type="file">

1. まず最初に画像ファイルを取得する

var eleFile = document.querySelector('#file');
  var reader = new FileReader()
  eleFile.addEventListener('change', function (event) {
    file = event.target.files[0];
    console.log(file)
    // The selected file is an image
    if (file.type.indexOf("image") == 0) {
      reader.readAsDataURL(file);    
    }
  });


2. この時点で画像ファイルが取り出されますが、jsのFileReaderオブジェクトの使い方を理解する必要があります。

FileReader オブジェクトを使用すると、ウェブアプリケーションは、ユーザーのコンピュータに保存されているファイル(または生データバッファ)の内容を非同期で読み取ることができます。

メソッドです。

<テーブル メソッド名 パラメータ 説明 アボート なし 割り込み読み出し readAsBinaryString ファイル バイナリコード readAsDataURL ファイル ファイルをDataURLとして読み込む 読み取りテキスト ファイル, [エンコーディング]. ファイルをテキストとして読み込む

  • readAsTextです。このメソッドには2つのパラメータがあり、そのうちの2つ目はテキストのエンコーディングで、デフォルト値はUTF-8です。このメソッドは非常にわかりやすく、ファイルをテキストとして読み込み、その結果がテキストファイルのコンテンツとなります。
  • readAsBinaryString: このメソッドはファイルをバイナリ文字列として読み込みます。これは通常バックエンドに渡され、バックエンドはファイルを文字列として保存することができます。
  • readAsDataURL: サンプルプログラムで使用しているメソッドです。このメソッドは、ファイルをdataで始まる文字列として読み取ります。この文字列の本質は、小さなファイルを直接文書に埋め込むためのスキームであるData URLです。この場合の小さなファイルとは、通常、画像やhtmlなどの形式のファイルである。(ここでbase64の手法が登場する)。

FileReaderの処理イベントの紹介

<テーブル イベント情報 説明 onabort 割り込み発生時 オンエラー オンアポート オンロード ファイルの読み込みが正常に完了したときに発生します。 オンロードエンド 読み取り完了トリガー(成功か失敗か オンロードスタート 読み出し開始時にトリガーされる オンプログレス 読書中

続けて、画像を取得した後、ファイルを加工するために変換する必要がありますが、このとき

var reader = new FileReader(); 
//read the file into the page as a Data URL 
  reader.readAsDataURL(file); 
  reader.onload=function(e) { 
    console.log(reader)
  } 



画像の取り込みと変換が終わったので、次は圧縮の準備です。

var eleFile = document.querySelector('#file');
  var reader = new FileReader()
  eleFile.addEventListener('change', function (event) {
    file = event.target.files[0];
    // console.log(file)
    // The selected file is an image
    if (file.type.indexOf("image") == 0) {
      var reader = new FileReader(); 
      // Read the file into the page as a Data URL 
        reader.readAsDataURL(file); 
        reader.onload=function(e) { 
          // console.log(this.result)
          var pre=document.getElementById("pre"); 
          pre.setAttribute("src", this.result)
          canvasDataURL(this.result, 100, 0.5)
        }     
    }
  })
  /* [canvasDataURL Compression via canvas]
   * @params path The format of the image in base64
   * @params targetWidth The width of the compressed image.  
   * @params quality The smaller the quality value, the more blurry the image will be.
   */
  function canvasDataURL(path, targetWidth, quality) {
    var img = new Image();
    img.src = path
    img.onload = function () {
        // var that = this
        // console.log(that)
        // default scaled compression
        var w = this.width
        var h = this.height
        scale = w / h;
        w = targetWidth
        h = targetWidth / scale
        var quality = quality; // default image quality is 0.7
        // Generate canvas
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        // Create property nodes
        var anw = document.createAttribute("width");
        anw.nodeValue = w;
        var anh = document.createAttribute("height");
        anh.nodeValue = h;
        canvas.setAttributeNode(anw);
        canvas.setAttributeNode(anh);
        ctx.drawImage(this, 0, 0, w, h);
        // The smaller the quality value, the more blurry the drawn image will be
        var base64 = canvas.toDataURL('image/jpeg', quality);
        var result = document.getElementById("result"); 
        result.setAttribute("src", base64)
    }
  }

非常にシンプルなので、圧縮された画像を取得することができます、上記のコードから、原理は、キャンバスのtoDataURLメソッドは、圧縮画像の形式と品質を指定することができます、キャンバスの情報を圧縮してbase64エンコーディングに変換し、圧縮を実現することです。

キャンバスでカードを作る

シナリオ 圧縮直後の画像と長押しで保存できる別の画像を合成する。

function drawCanvas (target) {
    var canvas = document.querySelector('#myCanvas')
    var ctx = canvas.getContext('2d')
    // is the ratio of physical pixels to device-independent pixels (dips) on the device
    var dp = window.devicePixelRatio || 1
    var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx. oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1
    var ratio = this.dp / this.backingStoreRatio
    var oldWidth = canvas.width
    var oldHeight = canvas.height
    canvas.width = oldWidth * ratio
    canvas.height = oldHeight * ratio
    canvas.style.width = oldWidth + 'px'
    canvas.style.height = oldHeight + 'px'
    ctx.scale(ratio, ratio)
    var headerImg = new Image()
    var bgImg = new Image()
    headerImg.src = target
    bgImg.src = '. /bg.png'
    headerImg.onload = (e) => {
      // The aspect ratio of the image
      var rate = headerImg.width / headerImg.height
      console.log(rate)
      bgImg.onload = (e) => {
        ctx.drawImage(headerImg, 10, 30, 50, (50 / rate))
        // Background image
        ctx.drawImage(bgImg, 0, 0, 150, 150)
        ctx.fillText('Awesome', 80, 70)
        var resultImg = new Image()
        resultImg.src = canvas.toDataURL('image/png', 1)
        resultImg.style.width = '100%'
        var cardImg = document.getElementById("cardImg"); 
        cardImg.setAttribute("src", resultImg.src)
      }
    }

先ほど取得した画像を、画像読み込み時にcanvasに描画し、同じくテキストなどで、最後にcanvasの情報をbase64エンコーディングに変換もします。この例は、次のコードで見ることができます。

この記事がお役に立てれば幸いです。また、Script Houseを応援していただければ幸いです。