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

vue實現上傳圖片新增水印

本文例項為大家分享了上傳圖片新增水印的具體實現程式碼,供大家參考,具體內容如下

1、封裝新增水印方法

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

2、專案中使用

<!-- 圖片上傳 -->
<div class="flex mt20" v-if="item.questionType === 4">
  <van-uploader
    v-model="item.imgUpload"
    multiple="true"
    lazy-load
    :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 { uploadhttp://www.cppcns.com
OSS } from '@/utils/oss'; import { parseTime,addWaterMarker } from '@/utils'; import { ImagePreview } from 'vant'; import Compressor from 'compressor'; const fileExtensions = ['xlsx','xls','docx','doc','pdf']; const quality = 0.2; //圖片壓縮質量 export default { methods: { // 上傳前 async handleBeforeImgUpload(img,detail) { if (!img) { return } return new Promise(async (resolve,reject) => { if (Array.isArray(img)) { if (img.length > 5) { this.$toast('一次最多上傳5張,請分批次上傳!') reject() } let blobs = [] for (const file of img) { // 大於512k的圖片則先壓縮 iwww.cppcns.com
f (file.size > 512 * 1024 && file.type.includes('image/')) { file = await this.compressor(file) } // 新增水印 let blob = await addWaterMarker(file) blob.name = file.name blobs.push(blob) } resolve(blobs) } else { // 大於512k的圖片則先壓縮 if (img.size > 512 * 1024 && img.type.includes('image/')) { img = await thihttp://www.cppcns.coms.compressor(img) } const blob = await addWaterMarker(img) blob.name = img.name resolve(blob) } }) },// 上傳後 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('上傳失敗,只能上傳照片!') // 上傳完成 if (index === img.length - 1) { $loading.hide() } return //forEach裡的return相當於continue } if (file.size > 1024 * 1024 * 10) { this.currentItem.imgUpload.splice(detail.index + index,1) this.$toast('檔案太大,單個檔案不能超過10M!') // 上傳完成 if (index === img.length - 1) { $loading.hide() } return } try { const { fileName,url } = await uploadOSS(file) this.currentItem.answer.push({ url,www.cppcns.com }) } catch (error) { this.currentItem.imgUpload.splice(detail.index + index,1) this.$toast('上傳失敗,請稍後重試!') console.error(error) } // 上傳完成 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('上傳失敗,只能上傳照片!') return } if (img.file.size >= 1024 * 1024 * 10) { this.currentItem.imgUpload.splice(detail.index,1) $loading.hide() this.$toast('檔案太大,不能超過10M!') return } // 大於512k則先壓縮 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('上傳失敗,請稍後重試!') console.error(error) } } }

感謝龍哥的指導;

3、效果如下

vue實現上傳圖片新增水印

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