vue實現上傳圖片新增水印(升級版)
阿新 • • 發佈:2021-09-14
專案實現上傳圖片新增水印升級版,供大家參考,具體內容如下
封裝水印方法
/** * 新增水印 * @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) } }) }) }
頁面中使用水印並壓縮圖片
<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}-{d} {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('上傳圖片失敗!請重新上傳') } },//圖片上傳成功回撥 handleSuccess(res) { // console.log(res); if (res) { XkGHsthis.$emit('imgData',res) } } } } </script> <style lang="s" 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>
水印方法更新版
/** * 壓縮和旋轉圖片 * @pwww.cppcns.comaram {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,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 // 先縮放水印再轉成圖片 markEle.style.transform = `scale(${scale})` const markImg = await htmlToCanvas(markEle) // 先壓縮和旋轉圖片 file = await compressor(file,(context,canvas) => { if(direction == 'rightDown'){ // 填充水印 右下角 context.drawImage(markImg,markImg.height) } else { // 填充水印 左下角 context.drawImage(markImg,15 * scale,markImg.height) } },maxWidth) resolve(file) } catch (error) { reject(error) } }) } function blobToImg(blob) { return new Promise((resolve,() => { let img = new Imagewww.cppcns.com() img.src = reader.result img.addEventListener('load',() => resolve(img)) }) reader.readAsDataURL(blob) }) } export function htmlToCanvas(el,allowTaint: false,backgroundColor //'transparent' //背景色 }) reshttp://www.cppcns.comolve(markImg) } catch (error) { reject(error) } }) }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。