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 での中国語入力方法の問題を素早く解決する

推薦する

CSS3でハートを描く

成果を達成する要件/機能: CSS + HTML を使用してハートを描く方法。分析:正方形と 2 つ...

純粋な CSS ヘッダーの実装コードを修正

純粋な CSS で固定ヘッダーを実装するのが難しい主な理由は 2 つあります。まず、最大のシェアを持...

JavaScript が重複したネットワークリクエストを防ぐ方法の例

序文開発中は、インターフェース要求の繰り返しによってさまざまな問題が発生することがよくあります。ネッ...

方言変換のためのApache Calciteコード

意味Calcite は、Sql を SqlNode に解析し、次に SqlNode を特定のデータベ...

ウェブサイトのユーザーエクスペリエンスデザイン(UE)

Google Reader で、JunChen が書いた「フロー理論と設計」というタイトルの投稿を見...

MYSQLデータベーステーブル構造の最適化方法の詳細な説明

この記事では、例を使用して、MYSQL データベース テーブル構造を最適化する方法を説明します。ご参...

CSS3 オーバーフロープロパティの説明

1. オーバーフローOverflow はオーバーフロー(コンテナ)です。コンテンツがコンテナを越える...

CentOS7.x のアンインストールとインストール MySQL5.7 の操作手順とエンコード形式の変更方法

1. MySQL 5.7 のアンインストール1.1查看yum是否安裝過mysql CD yum li...

MySQL 8.0 redo ログの詳細な分析

目次序文REDOログの生成REDOログ送信REDOログの保存と通知ユーザースレッドに通知要約する序文...

Docker-compose を使用して GitLab をデプロイする方法

Docker-compose は GitLab をデプロイします1. Dockerをインストールする...

使用場所によって混乱しやすいXHTMLタグ

<br />jb51.net では、常に記事のセマンティクスを重視してきましたが、HTM...

MySQL でメタデータ ロックがブロックされている場所を確認する方法

MySQL でメタデータ ロックがブロックされている場所を確認する方法手順: 1. セッション1の実...

CSS3のvar()を使用して実行時にscss変数の値を変更する詳細な説明

var() の紹介と使用法詳細 (MDN) IEは無効ですが、他の主流のブラウザは有効ですvar()...

Nginx を使用して https ルートドメイン名への 301 リダイレクトを実装するためのサンプル コード

SEO とセキュリティを考慮して、301 リダイレクトが必要です。以下の一般的な処理には Nginx...

nginx が複数のプロキシ層を通過して実際の送信元 IP を取得するプロセスの詳細な説明

質問Nginx は $remote_addr を実際の IP アドレスとして受け取りますが、実際には...