Vue はアップロードされた画像に透かしを追加する機能を実装します

Vue はアップロードされた画像に透かしを追加する機能を実装します

この記事では、Vueでアップロードされた画像に透かしを追加する具体的な実装コードを参考までに共有します。具体的な内容は次のとおりです。

1. カプセル化と透かしの方法

/**
 * 透かしを追加 * @param {blob} ファイル
 * @param {文字列} el
 * @returns {Promise}
 */
非同期関数 addWaterMarker(file, el = '#markImg') をエクスポートします。
  新しい Promise(async (resolve, reject) => { を返します。
    試す {
      // 最初に画像を圧縮して回転します。file = await compressed(file)
      // ファイル blob を画像に変換する let img = await blobToImg(file)

      // キャンバスを作成する let canvas = document.createElement('canvas')
      キャンバスの幅 = img.naturalWidth
      キャンバスの高さ = img.naturalHeight
      ctx = canvas.getContext('2d') とします。

      // アップロードされた画像を塗りつぶす ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

      // 透かし画像を生成する const markEle = document.querySelector(el)
      const markWidth = markEle.clientWidth
      定数スケール = キャンバス.幅 * 0.25 / マーク幅
      // 最初に透かしを拡大縮小してから画像に変換します markEle.style.transform = `scale(${scale})`
      const markImg = htmlToCanvas(markEle) を待機します

      // 透かしを塗りつぶす ctx.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)

      //キャンバスをblobに変換する
      canvas.toBlob(blob => 解決(blob))
    } キャッチ(エラー){
      拒否(エラー)
    }

  })
}

関数blobToImg(blob) {
  新しい Promise を返します ((resolve, reject) => {
    リーダーを新しいFileReader()にします
    リーダー.addEventListener('load', () => {
      img = new Image() とします。
      img.src = リーダー結果
      img.addEventListener('load', () => 解決(img))
    })
    リーダー.readAsDataURL(blob)
  })
}


エクスポート関数 htmlToCanvas(el, backgroundColor = 'rgba(0,0,0,.1)') {
  新しい Promise(async (resolve, reject) => { を返します。
    試す {
      const markImg = html2canvas(el, {を待つ
        scale: 2, //デフォルト値window.devicePixelRatioはここでは使用されません。モバイル側と一致させる必要がありますallowTaint: false, //汚染を許可しますuseCORS: true,
        backgroundColor //'transparent' //背景色})
      解決(マーク画像)
    } キャッチ(エラー){
      拒否(エラー)
    }
  })
}

/**
 * 画像を圧縮して回転する * @param {blob} ファイル
 * @param {number} 品質圧縮率 * @param {number} 最大幅
 * @returns {Promise}
 */
エクスポート関数コンプレッサー(ファイル、品質 = 0.6、最大幅 = 750) {
  新しいPromiseを返します(resolve => {
    新しいコンプレッサー(ファイル、{
      最大幅、
      品質、
      成功:解決、
      エラー(err) {
        コンソールログ(エラーメッセージ)
      }
    })
  })
}

2. プロジェクトでの使用

<!-- 画像のアップロード -->
<div class="flex mt20" v-if="item.questionType === 4">
  <バンアップローダー
    v-model="item.imgアップロード"
    複数="true"
    遅延読み込み
    :deletable="!isDisabled"
    :disabled="無効"
    @delete="handleDeleteImg({ ...引数, 項目 })"
    :before-read="handleBeforeImgUpload"
    :after-read="handleAfterImgUpload"
    @click.native="現在のアイテム = アイテム"
  />
</div>
    
<スクリプト>
輸入 {
  タスクの詳細を取得、
  ユーザー実行、
  送信フロー、
  拒否フロー、
} '@/api/myTask' から;

'@/utils/oss' から { uploadOSS } をインポートします。
'@/utils' から parseTime、addWaterMarker をインポートします。

'vant' から ImagePreview をインポートします。

'compressorjs' から Compressor をインポートします。

const fileExtensions = ['xlsx', 'xls', 'docx', 'doc', 'pdf'];

const quality = 0.2; //画像圧縮品質 export default {
  メソッド: {
  // アップロードする前に async handleBeforeImgUpload(img, detail) {
      もし(!img){
        戻る
      }
      新しい Promise(async (resolve, reject) => { を返します。
        Array.isArray(画像)の場合{
          画像の長さが5より大きい場合
            this.$toast('一度に最大 5 枚の写真をアップロードできます。数回に分けてアップロードしてください。')
            拒否する()
          }
          ブロブを [] にする
          for (const ファイル img) {
            // 512kより大きい画像は最初に圧縮されます if (file.size > 512 * 1024 && file.type.includes('image/')) {
              ファイル = this.compressor(ファイル) を待機します
            }
            // 透かしを追加 let blob = await addWaterMarker(file)
            blob.name = ファイル名
            blobs.push(blob)
          }
          解決(ブロブ)
        } それ以外 {
          // 512kより大きい画像は最初に圧縮する必要があります if (img.size > 512 * 1024 && img.type.includes('image/')) {
            img = this.compressor(img) を待機します
          }
          const blob = await addWaterMarker(img)
          blob.name = 画像名
          解決(ブロブ)
        }
      })
    },
    
    //アップロード後 async handleAfterImgUpload(img, detail) {
      試す {
        $読み込み中.表示()
        Array.isArray(画像)の場合{
          img.forEach(async ({ファイル},インデックス) => {
            if (!file.name || !file.type.includes('image/')) {
              this.currentItem.imgUpload.splice(detail.index + index, 1)
              this.$toast('アップロードに失敗しました。写真のみアップロードできます!')
              // アップロード完了 if (index === img.length - 1) {
                $loading.hide()
              }
              return // forEach の return は continue と同等です
            }
            ファイルサイズが 1024 * 1024 * 10 より大きい場合
              this.currentItem.imgUpload.splice(detail.index + index, 1)
              this.$toast('ファイルが大きすぎます。1 つのファイルは 10 MB を超えることはできません。')
              // アップロード完了 if (index === img.length - 1) {
                $loading.hide()
              }
              戻る
            }
            試す {
              const { ファイル名, url } = アップロードOSS(ファイル)を待つ
              this.currentItem.answer.push({
                URL、
              })
            } キャッチ(エラー){
              this.currentItem.imgUpload.splice(detail.index + index, 1)
              this.$toast('アップロードに失敗しました。しばらくしてからもう一度お試しください!')
              コンソール.エラー(エラー)
            }
            // アップロード完了 if (index === img.length - 1) {
              $loading.hide()
            }
          })
        } それ以外 {
          if (!img.file.type.includes('image')) {
            this.currentItem.imgUpload.splice(詳細インデックス、1)
            $loading.hide()
            this.$toast('アップロードに失敗しました。アップロードできるのは写真のみです!')
            戻る
          }
          (img.file.size >= 1024 * 1024 * 10) の場合 {
            this.currentItem.imgUpload.splice(詳細インデックス、1)
            $loading.hide()
            this.$toast('ファイルが大きすぎるため、10MB を超えることはできません。')
            戻る
          }
          // 512kより大きい場合は、まず圧縮します。let file = img.file
          const { ファイル名, url } = アップロードOSS(ファイル)を待つ
          this.currentItem.answer.push({
            URL、
          })
          $loading.hide()
        }
      } キャッチ(エラー){
        this.currentItem.imgUpload.splice(詳細インデックス、1)
        $loading.hide()
        this.$toast('アップロードに失敗しました。しばらくしてからもう一度お試しください!')
        コンソール.エラー(エラー)
      }
    }
 }

指導してくださったロング兄弟に感謝します。

3. 効果は以下のとおりです

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Vue で画像と画像の透かしを隠しテキスト情報とともに使用する方法
  • Vueはページに透かし効果を追加する機能を実装します
  • Vue は PDF.js を統合して PDF プレビューを実装し、透かしを追加する手順を実行します。
  • Vueはページ透かし機能を実装
  • Vueを使用して写真をアップロードする3つの方法
  • モバイル端末上のVue+Vantのアップローダーは、画像のアップロード、圧縮、回転の機能を実現します。
  • Vue+elementUI はフォームと画像のアップロードおよび検証機能の例を実装します
  • vue+elementUIは画像アップロード機能を実現します
  • VUEをベースに画像を選択してアップロードし、ページに表示します(画像は削除可能です)
  • Vue はアップロードした画像に透かしを追加できるようになりました (アップグレード版)

<<:  4 つの主要な SQL ランキング関数 ROW_NUMBER、RANK、DENSE_RANK、NTILE の使用方法の紹介

>>:  Linux での中国語入力方法の問題を素早く解決する

推薦する

MacでDockerがホストマシンにpingできない問題を解決する

解決Docker for Macに付属するLinux仮想マシン(軽量ですが、ソケットファイルを使用し...

MySQLとOracleの誤解の詳細な説明

目次本質的な違いデータベースセキュリティ権限スキーマの移行パターンオブジェクトの類似性スキーマオブジ...

MySQLのexplain型の詳細な説明

導入:多くの場合、さまざまな選択ステートメントを使用して必要なデータを照会した後、多くの人は作業が正...

iframe を介してフレームセットを本体に配置する

フレームセットと本文は同じレベルにあるため、本文にフレームセットを配置することはできません。まずペー...

ie8/ie9/ie10/ie11 chrome firefox を区別するための CSS コード

ウェブサイトの互換性のデバッグは本当に面倒です。今日のウェブサイト デザイナーは、以前よりもはるかに...

MySQLの詳細な分析で使用法と結果を説明します

序文日常業務では、実行に時間のかかる SQL ステートメントを記録するために、スロー クエリを実行す...

位置固定オフセット問題を解決する方法の詳細な説明

質問CSS 固定配置の position:fixed は非常に使いやすいです。ブラウザのビューポート...

標準的なHTMLの書き方は、Dreamweaverによって自動的に生成されるものとは異なります。

コードをコピーコードは次のとおりです。 <!--doctype はドキュメント タイプ htm...

Hyper-v仮想マシンを使用してCentos7をインストールする

目次導入準備するシステムイメージをダウンロードHyper-Vを有効にする新しい仮想ネットワークスイッ...

MySQLの構文、特殊記号、正規表現の詳細な説明

Mysql でよく使用される表示コマンド1. 現在のデータベース サーバー内のデータベースの一覧を表...

LinuxデバッガGDBの基本的な使い方の詳細な説明

目次1. 概要2. gdbデバッグ2.1. ブレークポイントを設定する2.1.1. ブレークポイント...

MySQL グリーン解凍バージョンのインストールと設定手順

手順: 1. MySQLデータベースをインストールする1. MySQL-5.6.17-winx64....

MySQL レプリケーション問題の 3 つのパラメータの分析

目次01 sql_slave_skip_counter パラメータ02 スレーブスキップエラーパラメ...

Linuxのtopコマンド出力の詳細な説明

序文皆さんは Linux で top コマンドを使ったことがあると思います。私は Linux に触れ...

JSはストップウォッチタイマーを実装します

この記事の例では、ストップウォッチタイマーを実装するためのJSの具体的なコードを参考までに共有してい...