Vue はアップロードした画像に透かしを追加できるようになりました (アップグレード版)

Vue はアップロードした画像に透かしを追加できるようになりました (アップグレード版)

vueプロジェクトでは、アップロードした画像に透かしを追加して参照できるようにするアップグレード版を実装しています。具体的な内容は次のとおりです。

カプセル化透かし方式

/**
 * 透かしを追加 * @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) {
        コンソールログ(エラーメッセージ)
      }
    })
  })
}

透かしを使用してページ内の画像を圧縮する

<テンプレート>
  <div>
    <el-アップロード
      アクション=""
      :headers="アップロードプロパティのヘッダー"
      リストタイプ="絵カード"
      :ファイルリストを表示="false"
      :http-request="fnアップロードリクエスト"
      :on-success="ハンドル成功"
      :before-upload="handleUpload"
      accept=".png,.jpg,.jpeg,.gif,.webp"
    >
      <div class="flex-center">
        <スロット></スロット>
      </div>
    </el-アップロード>
    <!-- 画像アップロードの透かし -->
    <div id="markImg">
      <div class="logo">
        <img src="@/assets/img/icon-logo.png" />
        テキストテキスト</div>
      <p>
        {{ parseTime(fileDate, '{y}-{m}-{d} {h}:{i}:{s}') }} 週 {{
          parseTime(ファイル日付、'{a}')
        }}
      </p>
      <p>{{ 実行者 }}</p>
    </div>
  </div>
</テンプレート>

<スクリプト>
輸入 {
  アクセストークンを取得、
  リフレッシュトークンを取得、
  アクセストークンTTLを取得する
} '@/utils/auth' から
'@/utils/ossImage' から { uploadOSS } をインポートします
'@/utils' から { parseTime、compressor、addWaterMarker } をインポートします。

エクスポートデフォルト{
  名前: 'インデックス',
  小道具: {
    ウォーターマークが必要:
      タイプ: ブール値、
      デフォルト: false
    },
    執行者: {
      タイプ: 文字列、
      デフォルト: ''
    }
  },
  データ() {
    戻る {
      fileDate: 新しいDate()
    }
  },
  作成された() {
    this.parseTime = 解析時間
  },
  計算: {
    ユーザーアカウントID() {
      this.$store.state.user.userAccountID を返します
    },
    アップロードプロパティ() {
      戻る {
        // アクション: `${process.env.VUE_APP_BASE_API}/api/image/upload`,
        ヘッダー: {
          // インターフェースにはトークンが必要な場合があります: "",
          認証: getAccessToken()
        },
        データ: {}
      }
    }
  },
  メソッド: {
    // beforeUpload_u(ファイル、ファイルリスト){
    // // console.log(ファイル、ファイルリスト);
    // var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
    // const extension = testmsg === 'png' || testmsg === 'jpg' || testmsg === 'jpeg' || testmsg === 'gif' || testmsg === 'webp'
    // 定数 isLimit10M = ファイルサイズ / 1024 / 1024 < 10
    // var bool = false;
    // if(拡張子 && isLimit10M){
    // ブール値 = true;
    // } それ以外 {
    // ブール値 = false;
    // }
    // if(!拡張子) {
    // this.$message.error('画像形式のファイルをアップロードしてください!');
    // ブール値を返します。
    // }
    // if(!isLimit10M) {
    // this.$message.error('アップロードに失敗しました。10Mを超えることはできません!');
    // ブール値を返します。
    // }
    // ブール値を返します。
    // },
    // ハンドル成功(res) {
    // コンソールログ(res);
    // res.code == 0 の場合 {
    // this.$emit('imgData', res.item);
    // this.$message.success('画像のアップロードに成功しました!');
    // } それ以外 {
    // this.$message.error('画像のアップロードに失敗しました!');
    // }
    // },
    // エラー処理(err){
    // this.$message.error('画像のアップロードに失敗しました!');
    // },

    // アップロード画像判定 handleUpload(file, fileList) {
      var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
      const拡張 =
        testmsg.toLowerCase() === 'png' ||
        testmsg.toLowerCase() === 'jpg' ||
        testmsg.toLowerCase() === 'jpeg' ||
        testmsg.toLowerCase() === 'gif' ||
        testmsg.toLowerCase() === 'webp'
      定数isLimit10M = ファイルサイズ / 1024 / 1024 < 10
      var ブール = false
      if (拡張子 && isLimit10M) {
        ブール値 = 真
      } それ以外 {
        ブール値 = 偽
      }
      if (!拡張子) {
        this.$message.error('画像形式のファイルをアップロードしてください!')
        ブール値を返す
      }
      10M を超えると
        this.$message.error('アップロードに失敗しました。10Mを超えることはできません!')
        ブール値を返す
      }
      ブール値を返す
    },
    // 画像をアップロード async fnUploadRequest(options) {
      試す {
        let file = options.file // ファイルを取得する
        this.fileDate = file.lastModifiedDate
        // 画像を圧縮する if (file.size > 512 * 1024 && file.type.includes('image/')) {
          ファイル = コンプレッサー(ファイル)を待つ
        }
        // ウォーターマークを追加するif (this.needWaterMark) {
          const ファイル名 = ファイル名
          ファイル = addWaterMarker(ファイル、'#markImg') を待機します
          file.name = ファイル名
        }
        res = await uploadOSS(ファイル) とします。
        // 返されるのは画像アドレスです this.$emit('imgData', res)
        this.$message.success('画像のアップロードに成功しました!')
      } キャッチ (e) {
        コンソール.log(e)
        this.$message.error('画像のアップロードに失敗しました。もう一度アップロードしてください')
      }
    },
    //画像アップロード成功コールバック handleSuccess(res) {
      // コンソールログ(res);
      もし(res){
        this.$emit('imgData', res)
      }
    }
  }
}
</スクリプト>

<style lang="scss" スコープ>
::v-deep .el-アップロード、
::v-deep .el-upload--picture-card {
  // 幅: 120px;
  高さ: 24px;
  高さ: 0;
  境界線: なし;
  行の高さ: 0;
  表示: ブロック;
  背景: #f5f6fb;
}
// ::v-deep .el-upload{
// 幅: 50px;
// }
.img-続き{
  幅: 50px;
  高さ: 24px;
  背景: #f5f6fb;
  .imgアイコン{
    色: #ccc;
  }
  .img-テキスト {
    フォントサイズ: 12px;
    高さ: 24px;
    色: #000;
  }
}
#マーク画像 {
  位置: 絶対;
  左: -9999999px;
  テキスト配置: 右;
  パディング: 10px 15px;
  .ロゴ {
    フォントの太さ: 600;
    フォントサイズ: 15px;
    色: #ffffff;

    ディスプレイ: フレックス;
    高さ: 21px;
    アイテムの位置を中央揃えにします。
    コンテンツの端揃え: flex-end;
    画像 {
      高さ: 21px;
      右マージン: 5px;
    }
  }
  p {
    上マージン: 6px;
    色: #ffffff;
    フォントサイズ: 12px;
    フォントの太さ: 400;
  }
}
</スタイル> 

透かし方式の更新版

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

/**
 * 透かしを追加 * @param {blob} ファイル
 * @param {文字列} el
 * @returns {Promise}
 */
 非同期関数 addWaterMarker(file, el = '#brandMarkImg', direction = 'rightDown') をエクスポートします。
  新しい Promise(async (resolve, reject) => { を返します。
    試す {
      定数最大幅 = 750
      const img = blobToImg(ファイル) を待機します
      const imgWidth = img.naturalWidth > maxWidth ? maxWidth : img.naturalWidth

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

      // 最初に画像を圧縮して回転します file = await compressed(file, (context, canvas) =​​> {
        if(方向 == 'rightDown'){
          // 透かしの右下隅を塗りつぶします context.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
        } それ以外 {
          // 透かしの左下隅を塗りつぶします context.drawImage(markImg, 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
        }
      }, 最大幅)
      解決(ファイル)
    } キャッチ(エラー){
      拒否(エラー)
    }

  })
}

関数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, {を待つ
        スケール: 2,
        allowTaint: false, //汚染を許可する useCORS: true,
        backgroundColor //'transparent' //背景色})
      解決(マーク画像)
    } キャッチ(エラー){
      拒否(エラー)
    }
  })
}

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

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

<<:  Navicat が MySql サーバーにリモート接続できない問題の解決策

>>:  Ubuntu 20.04 に cuda10.1 をインストールする手順 (グラフィック チュートリアル)

推薦する

OneProxy に基づいて MySQL の読み取り/書き込み分離と負荷分散を実装する

導入パート1: 冒頭に書いたOneProxy は、民間ソフトウェアによって完全に独立して開発された分...

nginx をプロキシ キャッシュとして使用する方法

キャッシュを使用する目的は、バックエンドの負荷を軽減し、Web サイトの同時実行性を向上させることで...

自動的にフォーカスを取得する要素入力ボックスの実装

最近のプロジェクトでフォームを作成するときに、コメント ボックスまで自動的にスクロールし、コメント ...

停止したすべてのDockerコンテナを1つのコマンドで再起動する

停止したすべてのDockerコンテナを1つのコマンドで再起動するdocker ps -a | gre...

React.cloneElement の使い方の詳しい説明

目次cloneElementの役割使用シナリオ新しい小道具を追加するプロップを変更するイベントカスタ...

Windows に MySQL 5.7.18 の解凍バージョンをインストールするチュートリアル

1. インストールプロセスMySQL バージョン: 5.7.18 1. my.ini ファイル(簡易...

MySQL オンライン DDL ツール gh-ost 原理分析

目次1. はじめに1.1 原則1.2 プロセス1.3 特徴1.4 githubアドレス2. テスト環...

MySQLデータベースで列を追加、削除、変更する方法

この記事では、例を使用して、MySQL データベースの列を追加、削除、および変更する方法について説明...

JavaScript 非同期プログラミングにおける Promise の初期の使用法の詳細な説明

1. 概要Promise オブジェクトは、ES6 で提案された非同期プログラミングの仕様です。非同期...

Web デザイン TabIndex 要素

TabIndex は、Tab キーを押して、定義された TabIndex 要素を順番に取得し、各要素...

Dockerイメージ作成の完全なプロセス

目次序文作成手順CentOSベースイメージを作成するコンテナを作成してカスタマイズするカスタムコンテ...

Vue vee-validateプラグインの簡単な使い方

目次1. インストール2. インポート3. 検証ルールを定義します(エクスポート用に js ファイル...

フロントエンドの上級者向けコースでは、JavaScript のストレージ機能の使い方を学習します。

目次序文背景実施計画の考え方js ストレージ機能ソリューション設計やっと要約する序文どの SaaS ...

レスポンシブ Web デザインが価値のない 5 つの理由

この記事は Tom Ewer の Managewp ブログからのもので、現在人気のレスポンシブ デザ...

Ubuntu 18.04 が VMware 仮想マシンでネットワークに接続できない問題の解決策

仮想マシン内のUbuntu 18.04がネットワークに接続できない問題の解決策は次のとおりですVMw...