vue實(shí)現(xiàn)上傳圖片添加水印
本文實(shí)例為大家分享了vue上傳圖片添加水印的具體實(shí)現(xiàn)代碼,供大家參考,具體內(nèi)容如下
1、封裝添加水印方法
/**
* 添加水印
* @param {blob} file
* @param {string} el
* @returns {Promise}
*/
export async function addWaterMarker(file, el = '#markImg') {
return new Promise(async (resolve, reject) => {
try {
// 先壓縮和旋轉(zhuǎn)圖片
file = await compressor(file)
// 將文件blob轉(zhuǎn)換成圖片
let img = await blobToImg(file)
// 創(chuàng)建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
// 先縮放水印再轉(zhuǎn)成圖片
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轉(zhuǎn)換成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, //此處不使用默認(rèn)值window.devicePixelRatio,需跟移動(dòng)端保持一致
allowTaint: false, //允許污染
useCORS: true,
backgroundColor //'transparent' //背景色
})
resolve(markImg)
} catch (error) {
reject(error)
}
})
}
/**
* 壓縮和旋轉(zhuǎn)圖片
* @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、項(xiàng)目中使用
<!-- 圖片上傳 -->
<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; //圖片壓縮質(zhì)量
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張,請(qǐng)分批次上傳!')
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相當(dāng)于continue
}
if (file.size > 1024 * 1024 * 10) {
this.currentItem.imgUpload.splice(detail.index + index, 1)
this.$toast('文件太大,單個(gè)文件不能超過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('上傳失敗,請(qǐng)稍后重試!')
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('上傳失敗,請(qǐng)稍后重試!')
console.error(error)
}
}
}
感謝龍哥的指導(dǎo);
3、效果如下

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹和選人功能
這篇文章主要介紹了Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹和選人功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
Vuejs實(shí)現(xiàn)帶樣式的單文件組件新方法
這篇文章主要為大家詳細(xì)為大家詳細(xì)介紹了Vuejs實(shí)現(xiàn)帶樣式的單文件組件的新方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
vue使用Google地圖的實(shí)現(xiàn)示例代碼
這篇文章主要介紹了vue使用Google地圖的實(shí)現(xiàn)示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12
Vue實(shí)現(xiàn)手機(jī)掃描二維碼預(yù)覽頁面效果
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)手機(jī)掃描二維碼預(yù)覽頁面效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03
vite項(xiàng)目配置less全局樣式的實(shí)現(xiàn)步驟
最近想實(shí)現(xiàn)個(gè)項(xiàng)目,需要配置全局less,本文主要介紹了vite項(xiàng)目配置less全局樣式的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02
Vue項(xiàng)目打包部署后瀏覽器自動(dòng)清除緩存問題的解決方法
這篇文章主要介紹了vue打包部署后 瀏覽器緩存問題,導(dǎo)致控制臺(tái)報(bào)錯(cuò)ChunkLoadError: Loading chunk failed的解決方案,文中有相關(guān)的圖文和代碼供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下2024-12-12
vue.js基于v-for實(shí)現(xiàn)批量渲染 Json數(shù)組對(duì)象列表數(shù)據(jù)示例
這篇文章主要介紹了vue.js基于v-for實(shí)現(xiàn)批量渲染 Json數(shù)組對(duì)象列表數(shù)據(jù),結(jié)合實(shí)例形式分析了vue.js使用v-for遍歷json格式數(shù)據(jù)渲染列表相關(guān)操作技巧,需要的朋友可以參考下2019-08-08
Vue.js 應(yīng)用性能優(yōu)化分析+解決方案
這篇文章主要介紹了Vue.js 應(yīng)用性能優(yōu)化分析以及解決方案,VueJS 是開發(fā)網(wǎng)站最受歡迎、最穩(wěn)定的 JavaScript 框架,但與其他框架一樣,如果您忽略它,性能就會(huì)受到影響,下面我們就一起來看看怎么才能讓性能提升吧2021-12-12

