uni-app为图片添加自定义水印(升级版)

前置内容

uni-app为图片添加自定义水印(解决生成图片不全问题)

UI 升级

现在水印样式变成这样了:
在这里插入图片描述
在这里插入图片描述

代码

<template><canvas v-if="waterMarkParams.display" canvas-id="waterMarkCanvas" :style="canvasStyle"/>
</template><script>export default {data() {return {waterMarkParams: {display: false, // 控制 canvas 创建与销毁canvasWidth: 300, // 默认宽度canvasHeight: 225, // 默认高度}}},computed: {canvasStyle() {return {position: 'fixed', // 移除到屏幕外left: '9999px',width: this.waterMarkParams.canvasWidth + 'px',height: this.waterMarkParams.canvasHeight + 'px'}}},methods: {chooseImage() {uni.chooseImage({sourceType: ['all'],success: async ({ tempFilePaths, tempFiles }) => {// 这里就得到了带水印的图片路径列表const imgFileArr = await this.callAddWaterMark(tempFilePaths)}})},// 因为有可能在相册中选择多个图片,所以这里要依次生成水印async callAddWaterMark(imgPathArr) {let results = []if(imgPathArr.length > 0) {let addIndex = 0while(addIndex < imgPathArr.length) {const tempFilePath = await this.addWaterMark(imgPathArr[addIndex])results.push(tempFilePath)addIndex = addIndex + 1}}return results},addWaterMark(src) {return new Promise((resolve, reject) => {// 获取图片信息,配置 canvas 尺寸uni.getImageInfo({src,success: res => {// 修复部分手机(如红米9)手机屏幕比较窄拍摄出来的图片水印压缩着覆盖的问题this.waterMarkParams.canvasWidth = Math.max(res.width, 886);this.waterMarkParams.canvasHeight = res.height;this.waterMarkParams.display = trueconsole.log('当前图片信息waterMarkParams:', this.waterMarkParams);// 等待 canvas 元素创建this.$nextTick(() => {let context = uni.createCanvasContext("waterMarkCanvas", this);/* 绘制 */const { canvasWidth, canvasHeight } = this.waterMarkParams// 绘制前清空画布context.clearRect(0, 0, canvasWidth, canvasHeight);// 将图片src放到cancas内,宽高必须为图片大小context.drawImage(src, 0, 0, canvasWidth, canvasHeight, canvasWidth, canvasHeight);// 防伪码的位置const fangweiY = 320;// 保证水印能完整显示出来const [x, y] = [canvasWidth / 2, canvasHeight - (fangweiY + 100)];context.translate(x, y);// 标记一下坐标系,更容易理解/* context.beginPath();context.lineWidth = 2;context.strokeStyle = 'white';context.moveTo(- x, 0);context.lineTo(x, 0);context.moveTo(0, -y);context.lineTo(0, canvasHeight - y);context.stroke();context.closePath(); */fillText(context, 0, 70, '上海市·金山区', 'bold 56px "Microsoft YaHei"', 'white', 'center');fillText(context, -20, 220, '16:08', 'bold 150px "Microsoft YaHei"', 'white', 'right');fillRect(context, -4, 100, 8, 120, '#346DFF');fillText(context, 20, 140, '2024.04.18', 'bold 40px "Microsoft YaHei"', 'white', 'left');fillText(context, 20, 210, '星期四  晴 21℃', 'bold 40px "Microsoft YaHei"', 'white', 'left');fillText(context, 0, fangweiY, `防伪:JY20240418160748XIAOMI`, 'bold 40px "Microsoft YaHei"', 'white', 'center');/* 绘制marker图标 */// 蓝色外圆fillCircle(context, -260, 30, 30, '#346DFF');// 白色内圆fillCircle(context, -260, 30, 12, 'white');// 蓝色三角fillTriangle(context, -260, 78, -235, 48, -285, 48, '#346DFF');// 坐标原点移动到画布右上角context.translate(canvasWidth / 2, -y);const [rectWidth, rectHeight, rectX, rectY, lineWidth, lineHeight] = [200, 90, -550, 60, 300, 6];// 右上角矩形fillRect(context, rectX, 60, rectWidth, rectHeight, '#346DFF');// 右上角下划线fillRect(context, rectX + rectWidth, rectY + rectHeight - lineHeight, lineWidth, lineHeight, '#346DFF');// 右上角姓名fillText(context, rectX + rectWidth / 2, 120, '鹏北海', 'bold 40px "Microsoft YaHei"', 'white', 'center');// 右上角手机号码fillText(context, rectX + rectWidth + lineWidth / 2, 120, '15888888888', 'bold 34px "Microsoft YaHei"', 'white', 'center');// 一定要加上一个定时器否则进入到页面第一次可能会无法正常拍照,后几次才正常setTimeout(() => {// 本次绘画完重开开始绘画,并且在绘画完毕之后再保存图片,不然页面可能会出现白屏等情况context.draw(false, () => {console.log('!!!!!开始绘画', canvasWidth, canvasHeight);uni.canvasToTempFilePath({canvasId: "waterMarkCanvas",fileType: "jpg",width: canvasWidth,height: canvasHeight,destWidth: canvasWidth,destHeight: canvasHeight,success: ({ tempFilePath }) => {console.log('绘制成功', tempFilePath);this.waterMarkParams.display = falseresolve(tempFilePath)},fail: err => {reject(err)console.log(err);}}, this)})}, 1000);})}})})// 绘制文字function fillText(context, x, y, content, font, fontStyle, textAlign) {// 保存当前绘图状态context.save();// 设置字体样式context.font = font// 设置文字颜色为白色context.fillStyle = fontStyle// 设置文字水平居中对齐context.textAlign = textAligncontext.fillText(content, x, y)// 恢复到之前保存的绘图状态,清除样式设置context.restore();}// 绘制圆function fillCircle(context, x, y, r, fillStyle) {// 保存当前绘图状态context.save();context.beginPath();context.arc(x, y, r, 0, 2 * Math.PI);context.fillStyle = fillStyle;context.fill();context.closePath();// 恢复到之前保存的绘图状态,清除样式设置context.restore();}// 绘制三角形function fillTriangle(context, x1, y1, x2, y2, x3, y3, fillStyle) {// 保存当前绘图状态context.save();context.beginPath();context.moveTo(x1, y1);context.lineTo(x2, y2);context.lineTo(x3, y3);context.fillStyle = fillStyle;context.fill();context.closePath();// 恢复到之前保存的绘图状态,清除样式设置context.restore();}// 绘制矩形function fillRect(context, x, y, width, height, fillStyle) {// 保存当前绘图状态context.save();context.fillStyle = fillStyle;context.fillRect(x, y, width, height);// 恢复到之前保存的绘图状态,清除样式设置context.restore();}},}}
</script>

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

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

相关文章

如何使用JSONB类型在PostgreSQL中存储和查询复杂的数据结构?

文章目录 解决方案1. 创建包含JSONB列的表2. 插入JSONB数据3. 查询JSONB数据4. 创建索引以优化查询性能 示例代码结论 在PostgreSQL中&#xff0c;JSONB是一种二进制格式的JSON数据类型&#xff0c;它允许你在数据库中存储和查询复杂的JSON数据结构。与普通的JSON类型相比&…

Springboot的Test单元测试操作

Springboot的Test单元测试操作 简单总结需要操作的步骤 1&#xff0c;导入依赖 2&#xff0c;创建目录&#xff08;目录和启动类的目录保持一致&#xff09; 3&#xff0c;添加注解 4&#xff0c;写方法测试 1&#xff0c;导入依赖 <dependency><groupId>org.spri…

Ts支持哪些类型和类型运算(下)

目录 1、条件判断 &#xff08;extends &#xff1f;&#xff09; 2、推导 infer 3、联合 | 4、交叉 & 5、映射类型 1、条件判断 &#xff08;extends &#xff1f;&#xff09; ts里的条件判断&#xff0c;语法为 T extends XXX ? true : false &#xff0c;叫做…

Docker - WEB应用实例

原文地址&#xff0c;使用效果更佳&#xff01; Docker - WEB应用实例 | CoderMast编程桅杆Docker - WEB应用实例 在之前的章节中&#xff0c;仅对普通容器进行了演示&#xff0c;但在实际中常常使用到 Docker 容器中的 WEB 应用程序。 运行一个WEB应用 拉取镜像 创建一个容器…

ROS机器人实战,对标古月老师HRMRP机器人(一)——机器人总体方案设计

咳咳&#xff01;这个是自己的毕业设计&#xff0c;内容比较多就拆开发。设计实现了一款SLAM移动机器人&#xff0c;加机械臂完成视觉识别抓取的&#xff0c;同时还有语音识别控制、QT上位机控制、Web网页控制。前几年看古月老师的视频&#xff0c;看到古月老师设计的HRMRP&…

Hadoop1X,Hadoop2X和hadoop3X有很大的区别么?

Hadoop的演进从Hadoop 1到Hadoop 3主要是为了提供更高的效率、更好的资源管理、更高的可靠性以及对更多数据处理方式的支持。下面是Hadoop 1, Hadoop 2, 和 Hadoop 3之间的主要区别和演进的原因&#xff1a; Hadoop 1 特点&#xff1a; 主要包括两大核心组件&#xff1a;HDFS&a…

【Hadoop】-HDFS的Shell操作[3]

目录 前言 一、HDFS集群启停命令 1.一键启停脚本可用 2.独立进程启停可用 二、文件系统操作命令 1、创建文件夹 2、查看指定目录下内容 3、上传文件到HDFS指定目录下 4、查看HDFS文件内容 5、下载HDFS文件 6、拷贝HDFS文件 7、追加数据到HDFS文件中 8、HDFS数据移…

【Python性能优化】list、array与set

list、array与set 详述测试代码 详述 本文对比 list 与 set 在插入和取值时的性能差异&#xff0c;以提供一条什么时候该选择什么数据类型的建议。先上结果&#xff1a; array 与 list 的不同&#xff1a; 内存方面 array 是 C array 的包装&#xff0c;它直接存储数据&#xf…

Sulley入门教学——简介、安装(Win7、VMware)

1、简介 Sulley 是由 Pedram Amini 和 Aaron Portnoy 开发的开源工具。它以 Python 编写&#xff0c;可以轻松地在不同平台上部署和使用。Sulley 提供了一个灵活且功能强大的框架&#xff0c;允许用户定义协议消息的结构、字段类型、边界条件和模糊测试策略。用户可以使用 Sul…

打破国外垄断|暴雨发布纯血国产电脑

要说现在国产手机这边已然进入纯自研模式&#xff0c;但电脑这边却还是仍未打破国外技术垄断。但就在刚刚&#xff0c;暴雨发布自研架构台式机open Station X &#xff0c;这是纯血鸿蒙系统之后国产又一款纯血产品发布&#xff01;标志的我们已经彻底打破西方在硬件及软件方面的…

每天五分钟机器学习:神经网络模型参数的选择

本文重点 在深度学习和人工智能的浪潮中,神经网络作为其中的核心力量,发挥着举足轻重的作用。然而,神经网络的性能并非一蹴而就,而是需要经过精心的参数选择和调优。 神经网络由大量的神经元组成,每个神经元之间通过权重进行连接。这些权重,以及神经元的偏置、激活函数…

Linux——进程基本概念中篇

Linux——进程基本概念中篇 文章目录 Linux——进程基本概念中篇一、通过系统调用创建进程——fork1.1 fork的理解1.2 fork的返回值 二、进程状态2.1 运行状态2.2 睡眠状态和休眠状态2.3 停止状态和死亡状态2.4 僵尸进程2.5 孤儿进程2.6 前台和后台进程 三、进程优先级3.1 查看…