vue實現(xiàn)上傳圖片添加水印
更新時間:2021年09月13日 11:50:23 作者:牛先森家的牛奶
這篇文章主要為大家詳細介紹了vue實現(xiàn)上傳圖片添加水印,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了vue上傳圖片添加水印的具體實現(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, //此處不使用默認值window.devicePixelRatio,需跟移動端保持一致 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、項目中使用
<!-- 圖片上傳 --> <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張,請分批次上傳!') 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、效果如下
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Vue.js遞歸組件實現(xiàn)組織架構(gòu)樹和選人功能
這篇文章主要介紹了Vue.js遞歸組件實現(xiàn)組織架構(gòu)樹和選人功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-07-07vue.js基于v-for實現(xiàn)批量渲染 Json數(shù)組對象列表數(shù)據(jù)示例
這篇文章主要介紹了vue.js基于v-for實現(xiàn)批量渲染 Json數(shù)組對象列表數(shù)據(jù),結(jié)合實例形式分析了vue.js使用v-for遍歷json格式數(shù)據(jù)渲染列表相關操作技巧,需要的朋友可以參考下2019-08-08