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, 0, 0, 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,0,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 { 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; //图片压缩质量

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的图片则先压缩

if (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 this.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,

})

} 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实现上传图片添加水印 的全部内容, 来源链接: utcz.com/p/239701.html

回到顶部