This article shares the specific implementation code of adding watermarks to uploaded pictures in Vue for your reference. The specific content is as follows 1. Encapsulation and watermarking method /** * Add watermark * @param {blob} file * @param {string} el * @returns {Promise} */ export async function addWaterMarker(file, el = '#markImg') { return new Promise(async (resolve, reject) => { try { // Compress and rotate the image first file = await compressor(file) // Convert the file blob to an image let img = await blobToImg(file) // Create a canvas let canvas = document.createElement('canvas') canvas.width = img.naturalWidth canvas.height = img.naturalHeight let ctx = canvas.getContext('2d') // Fill the uploaded image ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // Generate watermark image const markEle = document.querySelector(el) const markWidth = markEle.clientWidth const scale = canvas.width * 0.25 / markWidth // Scale the watermark first and then convert it to an image markEle.style.transform = `scale(${scale})` const markImg = await htmlToCanvas(markEle) // Fill watermark ctx.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height) //Convert canvas into 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, //The default value window.devicePixelRatio is not used here, it needs to be consistent with the mobile end allowTaint: false, //Allow pollution useCORS: true, backgroundColor //'transparent' //background color}) resolve(markImg) } catch (error) { reject(error) } }) } /** * Compress and rotate images * @param {blob} file * @param {number} quality compression ratio * @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. Use in the project <!-- Image Upload--> <div class="flex mt20" v-if="item.questionType === 4"> <van-uploader v-model="item.imgUpload" multiple="true" lazy-loading :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; //Image compression quality export default { methods: { // Before uploading async handleBeforeImgUpload(img, detail) { if (!img) { return } return new Promise(async (resolve, reject) => { if (Array.isArray(img)) { if (img.length > 5) { this.$toast('Upload up to 5 photos at a time, please upload in batches!') reject() } let blobs = [] for (const file of img) { // Images larger than 512k are compressed first if (file.size > 512 * 1024 && file.type.includes('image/')) { file = await this.compressor(file) } // Add watermark let blob = await addWaterMarker(file) blob.name = file.name blobs.push(blob) } resolve(blobs) } else { // Images larger than 512k should be compressed first 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) } }) }, //After uploading 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('Upload failed, only photos can be uploaded!') // Upload completed if (index === img.length - 1) { $loading.hide() } return //return in forEach is equivalent to continue } if (file.size > 1024 * 1024 * 10) { this.currentItem.imgUpload.splice(detail.index + index, 1) this.$toast('The file is too large, a single file cannot exceed 10M!') // Upload completed 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('Upload failed, please try again later!') console.error(error) } // Upload completed 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('Upload failed, only photos can be uploaded!') return } if (img.file.size >= 1024 * 1024 * 10) { this.currentItem.imgUpload.splice(detail.index, 1) $loading.hide() this.$toast('The file is too large and cannot exceed 10M!') return } // If it is larger than 512k, compress it first 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('Upload failed, please try again later!') console.error(error) } } } Thanks to Brother Long for his guidance; 3. The effects are as follows The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM. You may also be interested in:
|
>>: Quickly solve the Chinese input method problem under Linux
Table of contents 1. Install ESXi 2. Set up ESXi ...
This article example shares the specific code of ...
This article shares the installation and configur...
Result:Implementation code: <!DOCTYPE html>...
Table of contents Preface Fix infinite loop in fo...
This article shares the installation and configur...
Mysql multiple unrelated tables query data and pa...
Taking Windows as an example, Linux is actually t...
When using docker-compose for deployment, the out...
Preface: The most commonly used MySQL logical bac...
Preface: When using MySQL, you may encounter time...
Cerebro is an evolution of the Elasticsearch Kopf...
premise In complex scenarios, a lot of data needs...
Arrow function is a new feature in ES6. It does n...
1. Download MySQL from the official website: This...