Vue implements adding watermark to uploaded pictures

Vue implements adding watermark to uploaded pictures

This article shares the specific implementation code of adding watermarks to uploaded pictures in Vue for your reference. The specific content is as follows

1. Encapsulation and watermarking method

/**
 * Add watermark * @param {blob} file
 * @param {string} el
 * @returns {Promise}
 */
export async function addWaterMarker(file, el = '#markImg') {
  return new Promise(async (resolve, reject) => {
    try {
      // Compress and rotate the image first file = await compressor(file)
      // Convert the file blob to an image let img = await blobToImg(file)

      // Create a canvas let canvas = document.createElement('canvas')
      canvas.width = img.naturalWidth
      canvas.height = img.naturalHeight
      let ctx = canvas.getContext('2d')

      // Fill the uploaded image ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

      // Generate watermark image const markEle = document.querySelector(el)
      const markWidth = markEle.clientWidth
      const scale = canvas.width * 0.25 / markWidth
      // Scale the watermark first and then convert it to an image markEle.style.transform = `scale(${scale})`
      const markImg = await htmlToCanvas(markEle)

      // Fill watermark ctx.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)

      //Convert canvas into blob
      canvas.toBlob(blob => resolve(blob))
    } catch (error) {
      reject(error)
    }

  })
}

function blobToImg(blob) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.addEventListener('load', () => {
      let img = new Image()
      img.src = reader.result
      img.addEventListener('load', () => resolve(img))
    })
    reader.readAsDataURL(blob)
  })
}


export function htmlToCanvas(el, backgroundColor = 'rgba(0,0,0,.1)') {
  return new Promise(async (resolve, reject) => {
    try {
      const markImg = await html2canvas(el, {
        scale: 2, //The default value window.devicePixelRatio is not used here, it needs to be consistent with the mobile end allowTaint: false, //Allow pollution useCORS: true,
        backgroundColor //'transparent' //background color})
      resolve(markImg)
    } catch (error) {
      reject(error)
    }
  })
}

/**
 * Compress and rotate images * @param {blob} file
 * @param {number} quality compression ratio * @param {number} maxWidth
 * @returns {Promise}
 */
export function compressor(file, quality = 0.6, maxWidth = 750) {
  return new Promise(resolve => {
    new Compressor(file, {
      maxWidth,
      quality,
      success: resolve,
      error(err) {
        console.log(err.message)
      }
    })
  })
}

2. Use in the project

<!-- Image Upload-->
<div class="flex mt20" v-if="item.questionType === 4">
  <van-uploader
    v-model="item.imgUpload"
    multiple="true"
    lazy-loading
    :deletable="!isDisabled"
    :disabled="isDisabled"
    @delete="handleDeleteImg({ ...arguments, item })"
    :before-read="handleBeforeImgUpload"
    :after-read="handleAfterImgUpload"
    @click.native="currentItem = item"
  />
</div>
    
<script>
import {
  getTaskDetail,
  userExecute,
  submitFlow,
  rejectFlow,
} from '@/api/myTask';

import { uploadOSS } from '@/utils/oss';
import { parseTime, addWaterMarker } from '@/utils';

import { ImagePreview } from 'vant';

import Compressor from 'compressorjs';

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

const quality = 0.2; //Image compression quality export default {
  methods: {
  // Before uploading async handleBeforeImgUpload(img, detail) {
      if (!img) {
        return
      }
      return new Promise(async (resolve, reject) => {
        if (Array.isArray(img)) {
          if (img.length > 5) {
            this.$toast('Upload up to 5 photos at a time, please upload in batches!')
            reject()
          }
          let blobs = []
          for (const file of img) {
            // Images larger than 512k are compressed first if (file.size > 512 * 1024 && file.type.includes('image/')) {
              file = await this.compressor(file)
            }
            // Add watermark let blob = await addWaterMarker(file)
            blob.name = file.name
            blobs.push(blob)
          }
          resolve(blobs)
        } else {
          // Images larger than 512k should be compressed first if (img.size > 512 * 1024 && img.type.includes('image/')) {
            img = await this.compressor(img)
          }
          const blob = await addWaterMarker(img)
          blob.name = img.name
          resolve(blob)
        }
      })
    },
    
    //After uploading async handleAfterImgUpload(img, detail) {
      try {
        $loading.show()
        if (Array.isArray(img)) {
          img.forEach(async ({ file }, index) => {
            if (!file.name || !file.type.includes('image/')) {
              this.currentItem.imgUpload.splice(detail.index + index, 1)
              this.$toast('Upload failed, only photos can be uploaded!')
              // Upload completed if (index === img.length - 1) {
                $loading.hide()
              }
              return //return in forEach is equivalent to continue
            }
            if (file.size > 1024 * 1024 * 10) {
              this.currentItem.imgUpload.splice(detail.index + index, 1)
              this.$toast('The file is too large, a single file cannot exceed 10M!')
              // Upload completed if (index === img.length - 1) {
                $loading.hide()
              }
              return
            }
            try {
              const { fileName, url } = await uploadOSS(file)
              this.currentItem.answer.push({
                url,
              })
            } catch (error) {
              this.currentItem.imgUpload.splice(detail.index + index, 1)
              this.$toast('Upload failed, please try again later!')
              console.error(error)
            }
            // Upload completed if (index === img.length - 1) {
              $loading.hide()
            }
          })
        } else {
          if (!img.file.type.includes('image')) {
            this.currentItem.imgUpload.splice(detail.index, 1)
            $loading.hide()
            this.$toast('Upload failed, only photos can be uploaded!')
            return
          }
          if (img.file.size >= 1024 * 1024 * 10) {
            this.currentItem.imgUpload.splice(detail.index, 1)
            $loading.hide()
            this.$toast('The file is too large and cannot exceed 10M!')
            return
          }
          // If it is larger than 512k, compress it first let file = img.file
          const { fileName, url } = await uploadOSS(file)
          this.currentItem.answer.push({
            url,
          })
          $loading.hide()
        }
      } catch (error) {
        this.currentItem.imgUpload.splice(detail.index, 1)
        $loading.hide()
        this.$toast('Upload failed, please try again later!')
        console.error(error)
      }
    }
 }

Thanks to Brother Long for his guidance;

3. The effects are as follows

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • How to use pictures and picture watermarks with hidden text information in Vue
  • Vue implements adding watermark effect to the page
  • Vue integrates PDF.js to implement PDF preview and add watermark steps
  • Vue implements page watermark function
  • Three ways to upload pictures using Vue
  • The Uploader of Vue+Vant on the mobile terminal realizes the functions of uploading, compressing and rotating pictures
  • Vue+elementUI implements form and image upload and verification function example
  • vue+elementUI realizes the picture upload function
  • Based on VUE, select and upload pictures and display them on the page (pictures can be deleted)
  • Vue realizes adding watermark to uploaded pictures (upgraded version)

<<:  Introduction to the use of the four major sql ranking functions ROW_NUMBER, RANK, DENSE_RANK, NTILE

>>:  Quickly solve the Chinese input method problem under Linux

Recommend

Detailed explanation of MySQL information_schema database

1. Overview The information_schema database is th...

Web page printing thin line table + page printing ultimate strategy

When I was printing for a client recently, he aske...

A brief discussion on the perfect adaptation solution for Vue mobile terminal

Preface: Based on a recent medical mobile project...

Div nested html without iframe

Recently, when doing homework, I needed to nest a ...

MYSQL unlock and lock table introduction

MySQL Lock Overview Compared with other databases...

Let's talk about the performance of MySQL's COUNT(*)

Preface Basically, programmers in the workplace u...

Complete steps to install MySQL 8.0.x on Linux

MySQL Introduction to MySQL MySQL was originally ...

Problems with index and FROM_UNIXTIME in mysql

Zero, Background I received a lot of alerts this ...

Native JS to implement hover drop-down menu

JS implements a hover drop-down menu. This is a s...

Detailed explanation of MySQL sql_mode query and setting

1. Execute SQL to view select @@session.sql_mode;...

HTML Tutorial: Collection of commonly used HTML tags (4)

Related articles: Beginners learn some HTML tags ...

Detailed explanation of the use of MySQL group links

Grouping and linking in MYSQL are the two most co...

CentOS7 deploys version 19 of docker (simple, you can follow it)

1. Install dependency packages [root@localhost ~]...

Detailed steps for installing rockerChat in docker and setting up a chat room

Comprehensive Documentation github address https:...