Vue realizes adding watermark to uploaded pictures (upgraded version)

Vue realizes adding watermark to uploaded pictures (upgraded version)

The vue project implements an upgraded version of adding watermarks to uploaded pictures for your reference. The specific contents are as follows

Encapsulation watermark 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)
      }
    })
  })
}

Use watermarks and compress images in pages

<template>
  <div>
    <el-upload
      action=""
      :headers="uploadProps.headers"
      list-type="picture-card"
      :show-file-list="false"
      :http-request="fnUploadRequest"
      :on-success="handleSuccess"
      :before-upload="handleUpload"
      accept=".png,.jpg,.jpeg,.gif,.webp"
    >
      <div class="flex-center">
        <slot></slot>
      </div>
    </el-upload>
    <!-- Image upload watermark-->
    <div id="markImg">
      <div class="logo">
        <img src="@/assets/img/icon-logo.png" />
        Text text</div>
      <p>
        {{ parseTime(fileDate, '{y}-{m}-{d} {h}:{i}:{s}') }} Week {{
          parseTime(fileDate, '{a}')
        }}
      </p>
      <p>{{ executor }}</p>
    </div>
  </div>
</template>

<script>
import {
  getAccessToken,
  getRefreshToken,
  getAccessTokenTTL
} from '@/utils/auth'
import { uploadOSS } from '@/utils/ossImage'
import { parseTime, compressor, addWaterMarker } from '@/utils'

export default {
  name: 'index',
  props: {
    needWaterMark:
      type: Boolean,
      default: false
    },
    executor: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      fileDate: new Date()
    }
  },
  created() {
    this.parseTime = parseTime
  },
  computed: {
    userAccountID() {
      return this.$store.state.user.userAccountID
    },
    uploadProps() {
      return {
        // action: `${process.env.VUE_APP_BASE_API}/api/image/upload`,
        headers: {
          // The interface may require a token: "",
          Authorization: getAccessToken()
        },
        data: {}
      }
    }
  },
  methods: {
    // beforeUpload_u(file, fileList){
    // // console.log(file, fileList);
    // var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
    // const extension = testmsg === 'png' || testmsg === 'jpg' || testmsg === 'jpeg' || testmsg === 'gif' || testmsg === 'webp'
    // const isLimit10M = file.size / 1024 / 1024 < 10
    // var bool = false;
    // if(extension && isLimit10M){
    // bool = true;
    // } else {
    // bool = false;
    // }
    // if(!extension) {
    // this.$message.error('Please upload a picture format file!');
    // return bool;
    // }
    // if(!isLimit10M) {
    // this.$message.error('Upload failed, cannot exceed 10M!');
    // return bool;
    // }
    // return bool;
    // },
    // handleSuccess(res) {
    // console.log(res);
    // if (res.code == 0) {
    // this.$emit('imgData', res.item);
    // this.$message.success('Upload image successfully!');
    // } else {
    // this.$message.error('Failed to upload image!');
    // }
    // },
    // handleError(err){
    // this.$message.error('Failed to upload image!');
    // },

    // Upload picture judgment handleUpload(file, fileList) {
      var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
      const extension =
        testmsg.toLowerCase() === 'png' ||
        testmsg.toLowerCase() === 'jpg' ||
        testmsg.toLowerCase() === 'jpeg' ||
        testmsg.toLowerCase() === 'gif' ||
        testmsg.toLowerCase() === 'webp'
      const isLimit10M = file.size / 1024 / 1024 < 10
      var bool = false
      if (extension && isLimit10M) {
        bool = true
      } else {
        bool = false
      }
      if (!extension) {
        this.$message.error('Please upload a picture format file!')
        return bool
      }
      if (!isLimit10M) {
        this.$message.error('Upload failed, cannot exceed 10M!')
        return bool
      }
      return bool
    },
    // Upload image async fnUploadRequest(options) {
      try {
        let file = options.file // Get file
        this.fileDate = file.lastModifiedDate
        // Compress the image if (file.size > 512 * 1024 && file.type.includes('image/')) {
          file = await compressor(file)
        }
        // Add watermarkif (this.needWaterMark) {
          const fileName = file.name
          file = await addWaterMarker(file, '#markImg')
          file.name = fileName
        }
        let res = await uploadOSS(file)
        // What is returned is the image address this.$emit('imgData', res)
        this.$message.success('Upload image successfully!')
      } catch (e) {
        console.log(e)
        this.$message.error('Failed to upload the image! Please upload again')
      }
    },
    //Image upload successful callback handleSuccess(res) {
      // console.log(res);
      if (res) {
        this.$emit('imgData', res)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-upload,
::v-deep .el-upload--picture-card {
  // width: 120px;
  height: 24px;
  height: 0;
  border: none;
  line-height: 0;
  display: block;
  background: #f5f6fb;
}
// ::v-deep .el-upload{
// width: 50px;
// }
.img-cont {
  width: 50px;
  height: 24px;
  background: #f5f6fb;
  .img-icon {
    color: #ccc;
  }
  .img-text {
    font-size: 12px;
    height: 24px;
    color: #000;
  }
}
#markImg {
  position: absolute;
  left: -9999999px;
  text-align: right;
  padding: 10px 15px;
  .logo {
    font-weight: 600;
    font-size: 15px;
    color: #ffffff;

    display: flex;
    height: 21px;
    align-items: center;
    justify-content: flex-end;
    img {
      height: 21px;
      margin-right: 5px;
    }
  }
  p {
    margin-top: 6px;
    color: #ffffff;
    font-size: 12px;
    font-weight: 400;
  }
}
</style> 

Updated version of watermark method

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

/**
 * Add watermark * @param {blob} file
 * @param {string} el
 * @returns {Promise}
 */
 export async function addWaterMarker(file, el = '#brandMarkImg', direction = 'rightDown') {
  return new Promise(async (resolve, reject) => {
    try {
      const maxWidth = 750
      const img = await blobToImg(file)
      const imgWidth = img.naturalWidth > maxWidth ? maxWidth : img.naturalWidth

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

      // Compress and rotate the image first file = await compressor(file, (context, canvas) => {
        if(direction == 'rightDown'){
          // Fill the lower right corner of the watermark context.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
        } else {
          // Fill the lower left corner of the watermark context.drawImage(markImg, 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
        }
      }, maxWidth)
      resolve(file)
    } 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,
        allowTaint: false, //Allow pollution useCORS: true,
        backgroundColor //'transparent' //background color})
      resolve(markImg)
    } catch (error) {
      reject(error)
    }
  })
}

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:
  • Vue implements adding watermark to uploaded pictures
  • 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)

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

>>:  Solution to the problem that Navicat cannot remotely connect to MySql server

Recommend

MYSQL performance analyzer EXPLAIN usage example analysis

This article uses an example to illustrate the us...

Linux platform mysql enable remote login

During the development process, I often encounter...

Web Design Tutorial (3): Design Steps and Thinking

<br />Previous tutorial: Web Design Tutorial...

Linux system file sharing samba configuration tutorial

Table of contents Uninstall and install samba Cre...

Brief analysis of the various versions of mysql.data.dll driver

Here is the mysql driver mysql.data.dll Notice: T...

Summary of 6 Linux log viewing methods

As a backend programmer, you deal with Linux in m...

The pitfall record of the rubber rebound effect of iOS WeChat H5 page

Business requirements One of the projects I have ...

A line of CSS code that crashes Chrome

General CSS code will only cause minor issues wit...

Example of implementing circular progress bar in Vue

Data display has always been a demand that all wa...

Docker+nacos+seata1.3.0 installation and usage configuration tutorial

I spent a day on it before this. Although Seata i...

The implementation process of extracting oracle data to mysql database

In the migration of Oracle database to MySQL data...

RGBA alpha transparency conversion calculation table

Conversion between rgba and filter values ​​under...