【vue】vue + vant实现上传图片添加水印

目录

方法1:使用HTML2canvas

说明:

优点

缺点

依赖安装

方法2:使用canvas结合vant中组件

增加水印方法

在vue组件中使用

要点


方法1:使用HTML2canvas

使用html2canvas来处理水印的生成,需要就给水印元素转换为canvas图像并叠加到上传的图片。

<template><div><van-uploader :after-read="afterRead" /><!-- 水印元素 --><div id="watermark" style="display: none;"><div style="font-size: 20px; color: rgba(0, 0, 0, 0.3); transform: rotate(-45deg); position: absolute; top: 50%; left: 50%; transform-origin: center;">水印文本</div><!-- 如果需要图片水印,可以在这里添加图片元素 --><img src="path/to/watermark.png" style="position: absolute; bottom: 10px; right: 10px; width: 100px; height: 100px; opacity: 0.3;" /></div></div>
</template><script>
import { ref } from 'vue';
import html2canvas from 'html2canvas';export default {setup() {const afterRead = async (file) => {// 创建 canvas 元素const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');// 设置 canvas 尺寸为图片尺寸const img = await new Promise((resolve) => {const img = new Image();img.src = file.content;img.onload = () => resolve(img);});canvas.width = img.width;canvas.height = img.height;// 绘制原始图片ctx.drawImage(img, 0, 0);// 获取水印元素并转换为 canvasconst watermarkElement = document.getElementById('watermark');const watermarkCanvas = await html2canvas(watermarkElement, {logging: false,scale: window.devicePixelRatio, // 高清屏支持useCORS: true, // 启用跨域});// 将水印 canvas 绘制到主 canvas 上ctx.drawImage(watermarkCanvas, 0, 0, canvas.width, canvas.height);// 将 canvas 转换为 Blob 并替换文件内容canvas.toBlob((blob) => {file.file = blob;file.content = URL.createObjectURL(blob);}, 'image/png');};return {afterRead,};},
};
</script>

    说明:

    html2canvas 配置

    logging: false:禁用日志输出。

    scale: window.devicePixelRatio:支持高清屏。

    useCORS: true:启用跨域,确保图片资源可以被正确加载。

    绘制水印

    使用 html2canvas 将水印元素转换为 canvas 图像。

    将生成的水印 canvas 图像绘制到主 canvas 上。

    生成最终图片

    将主 canvas 转换为 Blob,并替换上传的文件内容。

    优点
    1. 灵活性高:可以将任何 HTML 元素转换为 canvas 图像,这意味着你可以使用 HTML 和 CSS 创建非常复杂的水印效果,比如带有图标、多行文本、不同字体和颜色等。

    2. 可视化设计:可以直接在页面上设计水印的样式,所见即所得,不需要通过代码去想象最终效果。

    3. 兼容性较好html2canvas 会尽可能地将页面元素渲染成与浏览器中显示一致的图像,减少了因手动绘制带来的兼容性问题。

    缺点
    1. 依赖外部库:需要引入 html2canvas 库,增加了项目的依赖和体积。

    2. 性能问题:将 HTML 元素转换为 canvas 图像的过程可能会有一定的性能开销,尤其是在水印元素复杂或者页面元素较多的情况下。

    3. 配置复杂:可能需要调整 html2canvas 的各种配置选项,以确保生成的图像符合预期,比如设置背景色、处理透明度等。

    依赖安装
    cnpm install compressorjs html2canvas

    方法2:使用canvas结合vant中组件

    使用纯canvas操作直接绘制水印文本

    vant的van-uploader组件提供了after-read事件,在其中调用水印处理函数

    增加水印方法
    /*** 添加水印* @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, 0, 0, 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 转换成 blobcanvas.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,allowTaint: false,useCORS: true,backgroundColor,});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);},});});
    }
    在vue组件中使用
    <template><div><van-uploaderv-model="fileList"multiple:after-read="afterRead":before-read="beforeRead"/><!-- 水印内容 --><div id="markImg" style="display: none;"><div style="font-size: 14px; color: rgba(255, 255, 255, 0.3);">水印文字</div></div></div>
    </template><script>
    import { addWaterMarker, compressor } from '@/utils/watermark';
    import Compressor from 'compressorjs';export default {data() {return {fileList: [], // vant 中图片上传的双向绑定};},methods: {// 上传前处理async beforeRead(file) {return new Promise(async (resolve, reject) => {if (Array.isArray(file)) {if (file.length > 5) {this.$toast('一次最多上传5张,请分批次上传!');reject();return;}let blobs = [];for (const f of file) {// 大于 512k 的图片则先压缩if (f.size > 512 * 1024 && f.type.includes('image/')) {f = await this.compressor(f);}// 添加水印let blob = await addWaterMarker(f);blob.name = f.name;blobs.push(blob);}resolve(blobs);} else {// 大于 512k 的图片则先压缩if (file.size > 512 * 1024 && file.type.includes('image/')) {file = await this.compressor(file);}const blob = await addWaterMarker(file);blob.name = file.name;resolve(blob);}});},// 上传后处理async afterRead(file) {// 处理上传逻辑console.log('上传成功', file);},// 压缩图片async compressor(file) {return new Promise((resolve) => {new Compressor(file, {quality: 0.6,success: resolve,error(err) {console.log(err.message);},});});},},
    };
    </script>
    要点

    addWaterMarker:添加水印的核心方法,负责将水印内容绘制到图片上。

    beforeRead:在图片上传前处理,包括压缩和添加水印。

    afterRead:图片上传后的处理逻辑。

    使用了 html2canvas 将水印内容转换为图片。

    使用了 compressorjs 对图片进行压缩。

    码字不易,各位大佬点点赞呗

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75692.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    【深度破解】爬虫反反爬核心技术实践:验证码识别与指纹伪装

    一、反爬技术体系全景图 现代Web应用的常见反爬手段&#xff1a; mermaid&#xff1a; graph TDA[反爬体系] --> B[行为特征检测]A --> C[验证码体系]A --> D[指纹追踪]B --> B1[请求频率]B --> B2[鼠标轨迹]B --> B3[页面停留时间]C --> C1[图形验证码…

    deepseek(2)——deepseek 关键技术

    1 Multi-Head Latent Attention (MLA) MLA的核心在于通过低秩联合压缩来减少注意力键&#xff08;keys&#xff09;和值&#xff08;values&#xff09;在推理过程中的缓存&#xff0c;从而提高推理效率&#xff1a; c t K V W D K V h t c_t^{KV} W^{DKV}h_t ctKV​WDKVht​…

    OpenGL绘制文本

    一&#xff1a;QPainter绘制 在 OpenGL 渲染的窗口中&#xff08;如 QOpenGLWidget&#xff09;&#xff0c;通过 QPainter 直接绘制文本。Qt 会自动将 2D 内容&#xff08;文本、图形&#xff09;与 OpenGL 内容合成。在paintGL()里面绘制&#xff0c;如果有其他纹理&#xf…

    从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.1.3前馈网络(FFN)与激活函数(GELU)优化

    👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.1.3 前馈网络(FFN)与激活函数(GELU)优化1. 前馈网络(FFN)的架构设计与数学原理1.1 FFN在Transformer中的核心作用2. GELU激活函数的数学特性与优化2.1 GELU的数学形式与近似计算3. 逐行代码实现…

    React 中的错误边界(Error Boundaries),如何使用它们捕获组件错误

    大白话React 中的错误边界&#xff08;Error Boundaries&#xff09;&#xff0c;如何使用它们捕获组件错误 在 React 里&#xff0c;错误边界就像是一个“小卫士”&#xff0c;专门负责在组件出现错误时挺身而出&#xff0c;避免整个应用因为一个小错误就崩溃掉。接下来我会详…

    数据库DBA认证,选哪个认证合适?

    从 Oracle、MySQL 到 云数据库&#xff0c;结合市场认可度、考试难度及职业回报&#xff0c;为你精选高性价比认证。 一、企业级数据库认证&#xff08;传统场景&#xff09; 1. Oracle认证 认证等级考试代码核心内容费用适合人群OCA1Z0-082SQL基础、数据库安装与配置$245零基…

    力扣刷题-热题100题-第24题(c++、python)

    234. 回文链表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/palindrome-linked-list/description/?envTypestudy-plan-v2&envIdtop-100-liked 常规法 数组是连续的存储空间&#xff0c;可以根据索引到达任意位置&#xff0c;链表只能一个个的顺…

    调用通义千问实现语音合成并将合成的音频通过扬声器播放

    1. 作者介绍 郭建东&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生 研究方向&#xff1a;机器视觉与人工智能 电子邮件&#xff1a;1229963266qq.com 高金年&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生&…

    Ubuntu软件包离线下载安装

    1、下载软件包tcpd&#xff0c;并在/var/cache/apt/archives目录中查看。 rooteducoder:~# apt-get install -d tcpd Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed:tcpd …

    您的数据是如何出现在暗网上的?

    暗网是互联网上的一个隐秘角落&#xff0c;人们可以在那里保持匿名。暗网经常与深网混淆&#xff0c;但它们并不完全相同。 深网是指网络上所有未被搜索引擎索引的内容。这包括电子邮件帐户、私人数据库和付费服务等。这并不违法&#xff0c;只是无法通过简单的 Google 搜索找…

    原型模式及其应用

    引言 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许通过复制现有对象来创建新对象&#xff0c;而无需通过构造函数来创建。这种模式通过克隆现有对象来创建新对象&#xff0c;从而避免了复杂的初始化过程。本文将探讨原型模式的好…

    thinkphp漏洞再现

    Thinkphp5x远程命令执行及getshell 1、开环境 2、使用工具攻击 开启工具 输入地址&#xff0c;点击漏洞检测 存在漏洞之后&#xff0c;选择漏洞&#xff0c;执行命令 3、也可以执行远程命令 执行命令 ?sindex/think\app/invokefunction&functioncall_user_func_array&…

    Day16 -实例:Web利用邮箱被动绕过CDN拿真实ip

    本想测试一下全局ping&#xff0c;刚好注册的时候收到了邮件&#xff0c;刚好去做一下复现。 原理&#xff1a;主动让对方站点给我们发邮件&#xff08;注册、修改密码、订阅推送等&#xff09;我们查看邮件原文&#xff0c;原文里存在真实的邮件站点ip 特点&#xff1a;邮件…

    vue3 数据监听(watch、watchEffect)

    1、watch 1.1基本使用 作用&#xff1a;数据监听 语法&#xff1a; watch(监听的数据, (改变后的数据, 改变前的数据) > { console.log(newVal, oldVal); }) 注意点&#xff1a;watch写法上支持一个或者多个监听源&#xff0c;这些监听源必须只能是getter/effect函数…

    网盘解析工具更新,解决了一些bug

    解析工具v1.2.1版本更新&#xff0c;本次是小版本更新&#xff0c;修复了一些bug。 之前小伙伴反应的网盘进入文件后不能返回上一级&#xff0c;现在这个bug修复了&#xff0c;已经可以点击了。 点击资源后会回到资源那一级目录&#xff0c;操作上是方便了不少。 增加了检查自…

    推荐1款简洁、小巧的实用收音机软件,支持手机和电脑

    聊一聊 没想到现在还有人喜欢听广播。 我一直以为听广播必须要用那种小广播机才可以。 原来手机或电脑上也是可以的。 今天给大家分享一款可以在电脑和手机上听广播的软件。 软件介绍 龙卷风收音机 电台广播收音机分电脑和手机两个版本。 电脑端无需安装&#xff0c;下载…

    六十天前端强化训练之第三十一天之Webpack 基础配置 大师级讲解(接下来几天给大家讲讲工具链与工程化)

    欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、Webpack 核心概念解析 二、实战&#xff1a;多资源打包配置&#xff08;含完整代码&#xff09; 三、配置深度解析&#xff08;重点部分说明&#xff09; 四、效果演示…

    机器学习——Bagging、随机森林

    相比于Boosting的集成学习框架&#xff0c;Bagging(Bootstrap Sampling&#xff0c;自助聚集法&#xff0c;又称为自助采样)作为一种自助聚集且并行化的集成学习方法&#xff0c;其通过组合多个基学习器的预测结果来提高模型的稳定性和泛化能力。其中随机森林是Bagging学习框架…

    【蓝桥杯】每日练习 Day13

    前言 今天做了不少题&#xff0c;但是感觉都太水了&#xff0c;深思熟虑之下主播决定拿出两道相对不那么水的题来说一下&#xff08;其实还是很水&#xff09;。 两道问题&#xff0c;一道是日期问题&#xff08;模拟&#xff09;&#xff0c;一道是区间合并问题。 日期差值 …

    HTML输出流

    HTML 输出流 JavaScript 中**「直接写入 HTML 输出流」**的核心是通过 document.write() 方法向浏览器渲染过程中的数据流动态插入内容。以下是详细解释&#xff1a; 一、HTML 输出流的概念 1. 动态渲染过程 HTML 文档的加载是自上而下逐行解析的。当浏览器遇到 <script&…