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 をインストールする手順 (グラフィック チュートリアル)

推薦する

docker ベースの redis-sentinel クラスターの構築例

1. 概要Redis Cluster は、Redis ノードのグループ間での高可用性とシャーディング...

JSで画面録画機能を作成する

OBS studioかっこいいですが、 JavaScriptもっとかっこいいです。では、 JavaS...

Redux Toolkit で Redux を簡素化する方法

目次Redux Toolkitが解決する問題何が含まれていますか? Redux Toolkit AP...

Vueはカウンターのシンプルな生成を実装します

この記事では、Vueカウンターの簡単な実装コードを例として紹介します。具体的な内容は以下のとおりです...

Docker で php-nginx-alpine イメージをゼロから構築する方法

これまでにも Docker 環境でいくつかのプロジェクトを実行したことはありますが、まだイメージをよ...

Vue3は独自のページングコンポーネントをカプセル化します

この記事の例では、vue3 が独自のページングコンポーネントをカプセル化する具体的なコードを参考まで...

MySQL でプロファイルを使用する方法のチュートリアル

プロフィールとは何ですか?特定の SQL のパフォーマンスを分析したい場合に使用できます。プロファイ...

Iframe 適応高さコードに関する 3 つの議論

B/S システム インターフェースを構築する場合、メイン ページ index.html 内に他のペー...

MySQLのジョイントインデックス機能の分析と使用例

この記事では、例を使用して、MySQL 共同インデックスの機能と使用方法を説明します。ご参考までに、...

MySQL GROUP_CONCAT 制限の解決

効果: GROUP_CONCAT関数は、フィールド値を文字列に連結することができます。デフォルトの区...

Linux カーネル デバイス ドライバー 高度な文字デバイス ドライバーのメモ

/****************** * 高度な文字デバイス ドライバー ***********...

Navicat がデータベース データ構造をインポートする際に発生するエラー datetime(0) の SQL レポートの問題を解決します。

エラー発生: MySQL 5.7 から SQL にデータベースをエクスポートし、それを MySQL ...

MySQL Community Server 5.7.19 インストール ガイド (詳細)

MySQL公式サイトのzipファイルのダウンロードリンク https://dev.mysql.co...

Ubuntu 18.04 (物理マシン) で OpenWRT 開発環境を構成する方法

1. 仮想マシン(物理マシン)をインストールする仮想マシンまたは物理マシンにインストールできます。 ...