1. 程式人生 > 程式設計 >vue實現上傳圖片新增水印(升級版)

vue實現上傳圖片新增水印(升級版)

專案實現上傳圖片新增水印升級版,供大家參考,具體內容如下

封裝水印方法

/**
 * 新增水印
 * @param {blob} file
 * @param {string} el
 * @returns {Promise}
 */
export async function addWaterMarker(file,el = '#markImg') {
  return new Promise(async (resolve,reject) => {
    try {
      // 先壓縮和旋轉圖片
      file = await compressor(file)
      // 將檔案blob轉換成圖片
      let img = await blobToImg(file)

      // 建立canvas畫布
      let canvas = document.createElement('canvas')
      canvas.width = img.naturalWidth
      canvas.height = img.naturalHeight
      let ctx = canvas.getContext('2d')

      // 填充上傳的圖片
      ctx.drawImage(img,canvas.width,canvas.height)

      // 生成水印圖片
      const markEle = document.querySelector(el)
      const markWidth = markEle.clientWidth
      const scale = canvas.width * 0.25 / markWidth
      // 先縮放水印再轉成圖片
      markEle.style.transform = `scale(${scale})`
      const markImg = await htmlToCanvas(markEle)

      // 填充水印
      ctx.drawImage(markImg,canvas.width - markImg.width - 15 * scale,canvas.height - markImg.height - 15 * scale,markImg.width,markImg.height)

      // 將canvas轉換成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,.1)') {
  return new Promise(async (resolve,reject) => {
    try {
      const markImg = await html2canvas(el,{
        scale: 2,//此處不使用預設值window.devicePixelRatio,需跟移動端保持一致
        allowTaint: false,//允許汙染
        useCORS: true,backgroundColor //'transparent'  //背景色
      })
      resolve(markImg)
    } catch (error) {
      reject(error)
    }
  })
}

/**
 * 壓縮和旋轉圖片
 * @param {blob} file
 * @param {number} quality  壓縮比例
 * @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)
      }
    })
  })
}

頁面中使用水印並壓縮圖片

<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>
    <!-- 圖片上傳水印 -->
    <div id="markImg">
      <div class="logo">
        <img src="@/assets/img/icon-logo.png" />
        文字文字
      </div>
      <p>
        {{ parseTime(fileDate,'{y}-{m}-{d} {h}:{i}:{s}') }} 周{{
          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: {
          // 介面可能要帶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('請上傳圖片格式檔案!');
    //     return bool;
    //   }
    //   if(!isLimit10M) {
    //     this.$message.error('上傳失敗,不能超過10M!');
    //     return bool;
    //   }
    //   return bool;
    // },// handleSuccess(res) {
    //   console.log(res);
    //   if (res.code == 0) {
    //     this.$emit('imgData',res.item);
    //     this.$message.success('上傳圖片成功!');
    //   } else {
    //     this.$message.error('上傳圖片失敗!');
    //   }
    // },// handleError(err){
    //   this.$message.error('上傳圖片失敗!');
    // },// 上傳圖片判斷
    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('請上傳圖片格式檔案!')
        return bool
      }
      if (!isLimit10M) {
        this.$message.error('上傳失敗,不能超過10M!')
        return bool
      }
      return bool
    },// 上傳圖片
    async fnUploadRequest(options) {
      try {
        let file = options.file // 拿到 file
        this.fileDate = file.lastModifiedDate
        // 壓縮圖片
        if (file.size > 512 * 1024 && file.type.includes('image/')) {
          file = await compressor(file)
        }
        // 新增水印
        if (this.needWaterMark) {
          const fileName = file.name
          file = await addWaterMarker(file,'#markImg')
          file.name = fileName
        }
        let res = await uploadOSS(file)
        // 返回的就是圖片地址
        this.$emit('imgData',res)
        this.$message.success('上傳圖片成功!')
      } catch (e) {
        console.log(e)
        this.$message.error('上傳圖片失敗!請重新上傳')
      }
    },//圖片上傳成功回撥
    handleSuccess(res) {
      // console.log(res);
      if (res) {
   XkGHs
this.$emit('imgData',res) } } } } </script> <style lang="s" 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>

vue實現上傳圖片新增水印(升級版)

水印方法更新版

/**
 * 壓縮和旋轉圖片
 * @pwww.cppcns.comaram {blob} file
 * @param {number} quality  壓縮比例
 * @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,error(err) {
        console.log(err.message)
      }
    })
  })
}

/**
 * 新增水印
 * @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

      // 生成水印圖片
      const markEle = document.querySelector(el)
      const scale = imgWidth * 0.25 / markEle.clientWidth
      // 先縮放水印再轉成圖片
      markEle.style.transform = `scale(${scale})`
      const markImg = await htmlToCanvas(markEle)

      // 先壓縮和旋轉圖片
      file = await compressor(file,(context,canvas) => {
        if(direction == 'rightDown'){
          // 填充水印 右下角
          context.drawImage(markImg,markImg.height)
        } else {
          // 填充水印 左下角
          context.drawImage(markImg,15 * scale,markImg.height)
        }
      },maxWidth)
      resolve(file)
    } catch (error) {
      reject(error)
    }

  })
}

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

export function htmlToCanvas(el,allowTaint: false,backgroundColor //'transparent'  //背景色
      })
      reshttp://www.cppcns.comolve(markImg)
    } catch (error) {
      reject(error)
    }
  })
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。