vue實現(xiàn)上傳圖片添加水印(升級版)
更新時間:2021年09月13日 17:36:35 作者:牛先森家的牛奶
這篇文章主要為大家詳細介紹了vue實現(xiàn)上傳圖片添加水印的升級版,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
vue項目實現(xiàn)上傳圖片添加水印升級版,供大家參考,具體內(nèi)容如下
封裝水印方法
/** * 添加水印 * @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,需跟移動端保持一致 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) } }) }) }
頁面中使用水印并壓縮圖片
<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}-ublnpf9mb {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('上傳圖片失??!請重新上傳') } }, //圖片上傳成功回調(diào) handleSuccess(res) { // console.log(res); if (res) { this.$emit('imgData', res) } } } } </script> <style lang="scss" 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>
水印方法更新版
/** * 壓縮和旋轉(zhuǎn)圖片 * @param {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, quality, drew, success: resolve, 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 // 先縮放水印再轉(zhuǎn)成圖片 markEle.style.transform = `scale(${scale})` const markImg = await htmlToCanvas(markEle) // 先壓縮和旋轉(zhuǎn)圖片 file = await compressor(file, (context, canvas) => { if(direction == 'rightDown'){ // 填充水印 右下角 context.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height) } else { // 填充水印 左下角 context.drawImage(markImg, 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height) } }, maxWidth) resolve(file) } 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, allowTaint: false, //允許污染 useCORS: true, backgroundColor //'transparent' //背景色 }) resolve(markImg) } catch (error) { reject(error) } }) }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue+element實現(xiàn)下拉菜單并帶本地搜索功能示例詳解
這篇文章主要介紹了vue+element實現(xiàn)下拉菜單并帶本地搜索功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09vue?eslint報錯:Component?name?“xxxxx“?should?always?be?
新手在使用腳手架時總會報各種錯,下面這篇文章主要給大家介紹了關(guān)于vue?eslint報錯:Component?name?“xxxxx“?should?always?be?multi-word.eslintvue的4種解決方案,需要的朋友可以參考下2022-07-07vue-admin-template配置快捷導(dǎo)航的代碼(標(biāo)簽導(dǎo)航欄)
這篇文章主要介紹了vue-admin-template配置快捷導(dǎo)航的方法(標(biāo)簽導(dǎo)航欄),本文通過實例代碼給大家介紹的非常詳細,對大家學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09vue使用原生js實現(xiàn)滾動頁面跟蹤導(dǎo)航高亮的示例代碼
這篇文章主要介紹了vue使用原生js實現(xiàn)滾動頁面跟蹤導(dǎo)航高亮的示例代碼,滾動頁面指定區(qū)域?qū)Ш礁吡?。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10