【小程序图片水印】微信小程序图片加水印功能 canvas绘图

news2024/12/22 20:45:20

看看效果

在这里插入图片描述

实现步骤:

1.选择图片

/* 选择背景图片 对图片的大小以及类型做一下限制 */
chooseImage(e) {
	uni.chooseImage({
		count: 1,
		success: (res) => {
			let index = res.tempFilePaths[0].lastIndexOf(".");
			let imgUrl = res.tempFilePaths[0].substr(index + 1);

			if (imgUrl != "png" && imgUrl != "jpg" && imgUrl != "jpeg") {
				uni.showToast({
					title: '请上传jpg、jpeg、png类型的图片',
					icon: 'none'
				});
				return
			}
			if (res.tempFiles[0].size / 1024 < 1024 * 1024 * 20) {
				this.originImg = res.tempFilePaths[0]
				this.imageSrc = res.tempFilePaths[0]
				this.loadImage();
			} else {
				uni.showToast({
					title: '图片大小不能超过20M,当前大小' + (res.tempFiles[0].size / 1024).toFixed(
						2) + 'KB',
					icon: 'none'
				})
			}
		},
	});
},

图片展示区域计算

/* 将图片加载到画布  */
loadImage() {
	uni.showLoading({
		title: "图片加载中...",
	});

	/* 获取图片信息  */
	uni.getImageInfo({
		src: this.imageSrc,
		success:(res) => {
			let imgH = res.height;
			let imgW = res.width;

			/* 图片的宽高比  */
			IMG_RATIO = imgW / imgH;

			/**
			 * 如果图片更高一些,为确保图片能够完整在视窗内显示需如下处理
			 * 1. 缩放图片的高为 视窗高度减去底部菜单按钮高度(120)
			 * 2. 根据图片缩放后的高度,根据图片宽高比计算图片的宽度
			 * 3. 如果步骤2计算的图片宽度大于屏幕宽度,则需要再次调整图片宽度为视窗宽度-margin(10)
			 * 4. 根据步骤3的宽度,结合图片宽高比重新计算图片的高度
			 */
			if (IMG_RATIO < 1 && (SCREEN_HEIGHT - 133) * IMG_RATIO < SCREEN_WIDTH - 10) {
				IMG_REAL_W = (SCREEN_HEIGHT - 133) * IMG_RATIO;
				IMG_REAL_H = SCREEN_HEIGHT - 133;
			} else {
				IMG_REAL_W = SCREEN_WIDTH - 10;
				IMG_REAL_H = IMG_REAL_W / IMG_RATIO;
			}
				/* 裁剪区域的宽高同图片尺寸  */
				this.cropperW=IMG_REAL_W,
				this.cropperH=IMG_REAL_H,
				/* 上下左右各留一定的margin已便更好的拖动裁剪区域  */
				this.cropperL=Math.ceil((SCREEN_WIDTH - IMG_REAL_W) / 2),
				/* 留出底部操作按钮位置 70  */
				this.cropperT=uni.getStorageSync("navHeight"),
				// 图片缩放值
				this.imageW=IMG_REAL_W,
				this.imageH=IMG_REAL_H,
				this.isShowImg=true,

				uni.hideLoading();
				this.finish()
		},
	});
},

图片水印canvas绘制

/* 完成裁剪,输出裁剪后的图片路径  */
finish() {
	uni.showLoading({
		title: "图片生成中...",
	});
	// 水印加载
	const ctx = uni.createCanvasContext("myCanvas", this);
	ctx.clearRect(0, 0, IMG_REAL_W, IMG_REAL_H);
	// 将图片写入画布
	ctx.drawImage(this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H);
	ctx.save();
	ctx.beginPath();

	if (['alone'].includes(this.changeMode)) {
		ctx.beginPath()
		ctx.setFontSize(this.changeSize)
		ctx.setFillStyle(this.changeColor)
		ctx.fillText(this.changeText, this.imageW - this.changeSize * this.changeText.length - 10, this.imageH - this.changeSize)
	}

	if (['level'].includes(this.changeMode)) {
		for (let j = 1; j < 12; j++) {
			ctx.beginPath()
			ctx.setFontSize(this.changeSize)
			ctx.setFillStyle(this.changeColor)
			ctx.fillText(this.changeText, 0, 50 * j)
			for (let i = 1; i < 12; i++) {
				ctx.beginPath()
				ctx.setFontSize(this.changeSize)
				ctx.setFillStyle(this.changeColor)
				ctx.fillText(this.changeText, (15 + (this.changeSize - 1) * this.changeText.length) * i, 50 * j)
			}
		}
	}

	if (["incline"].includes(this.changeMode)) {
		ctx.font = this.changeSize + "px serif";
		ctx.fillText(this.changeText, -1000, -1000)
      const textWidth = ctx.measureText(this.changeText + "").width
		const _textWidth = textWidth * 1.5
		const _textHeight = 40
		const xSize = Math.floor(this.imageW / _textWidth + 1)
     const ySize = Math.floor(this.imageH / _textHeight + 1)
		// 开始绘制水印:
      // 左右各多出一半图片宽度的水印,是用来处理旋转后盖住空白部分的;上下同理:
		for (var x = 0; x < xSize * 2; x++) {
        // x控制横向多少个水印:
        for (var y = 0; y < ySize * 2; y++) {
          // y控制纵向多少个水印:
          // 绘制文字  注意::绘制斜体文字 旋转以后会发生位移,所以必须在旋转之后进行位置的调整;
          this.drawText(ctx, (this.imageW), (this.imageH), -this.imageW / 2 + ((x * _textWidth)), -this.imageH / 2 + ((y * _textHeight)))
        }
      }
	}

	ctx.draw(true, () => {
		// 获取画布要裁剪的位置和宽度   均为百分比 * 画布中图片的宽度    保证了在微信小程序中裁剪的图片模糊  位置不对的问题 canvasT = (this.cutT / this.cropperH) * (this.imageH / pixelRatio)
		var canvasW = IMG_REAL_W;
		var canvasH = IMG_REAL_H;
		var canvasL = 0;
		var canvasT = 0;
		uni.canvasToTempFilePath({
				x: canvasL,
				y: canvasT,
				width: canvasW,
				height: canvasH,
				// destWidth: canvasW,
				// destHeight: canvasH,
				quality: +this.quality,
				fileType: this.fileType,
				canvasId: "myCanvas",
				success: (res) => {
					uni.hideLoading();
					// this.saveImg()
					this.waterImgSrc = res.tempFilePath
				},
				fail: (err) => {
					uni.hideLoading();
					uni.showToast({
						title: "图片截取失败!",
						icon: "none",
					});
				},
			},
			this
		);
	});
},
drawText(ctx, imgWidth, imgHeight, x, y) {
	var text = this.changeText;
	ctx.save(); //保存原来的状态  绘制字体都是需要旋转倾斜  那么之前绘制的图片就要进行状态的保存
	// ctx.globalAlpha = 0.6
	// 移动到中心点,再旋转相当于按照之前的原点旋转了
	ctx.translate(imgWidth / 2, imgHeight / 2)
	ctx.rotate(-Math.PI / 6); //绘制倾斜字体
	// 移动回原来的位置:
	ctx.translate(-imgWidth / 2, -imgHeight / 2)
	//ctx.translate(tsx, tsy); //发生位移进行位移的恢复
	ctx.font = this.changeSize + "px serif";
	ctx.fillStyle = this.changeColor;
	ctx.fillText(text, x, y);
	ctx.restore(); //状态的恢复
},

图片保存逻辑

saveImg() {
	const path = this.waterImgSrc
	uni.showShareImageMenu({ 
		path,
		success: (res)=>{
			console.log(res)
			wx.showToast({
				title: '生成成功!',
				icon: 'success',
				duration: 2000//持续的时间
			})
		},
		fail: (err)=> {
			console.log(err)
			wx.showToast({
				title: '生成失败!',
				icon: 'none',
				duration: 2000//持续的时间
			})
		}
	})
},

感觉有用的话,可以打赏一把么?一毛不嫌少,十块不嫌多
在这里插入图片描述
更多详细代码请关注公众号索取(备注:公众号):
在这里插入图片描述

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

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

相关文章

【设计模式】第3节:设计模式概论

设计模式不是代码&#xff0c;而是某类问题的通用方案。设计模式的本质是提高软件的维护性、通用性和扩展性&#xff0c;并降低软件的复杂度。一共有24种设计模式&#xff0c;可以分为创建型模式、结构型模式和行为型模式三大类。设计模式中比较重要的有&#xff1a;单例模式、…

seata at模式死锁

背景 mysql版本为5.7,在mysql的系统表中&#xff0c;有一个lock_deadlocks的指标 SELECT * FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE name LIKE %deadlock%该指标的count值记录了数据库实例从启动到现在的死锁次数&#xff0c;我们通过普罗米修斯的mysql探针&#xff0…

软件外包开发的代码质量控制

软件代码质量控制是确保软件项目成功的重要组成部分。以下是一些常见的软件代码质量控制方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.代码审查&#xff08;Code Review&#xff09; 通过定…

Zynq UltraScale+ XCZU15EG 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优越性4、详细设计方案设计原理框图IMX214 摄像头及其配置D-PHY 模块CSI-2-RX 模块Bayer转RGB模块伽马矫正模块VDMA图像缓存Video Scaler 图像缓存DP 输出 5、vivado工程详解PL端FPGA硬件设计…

目前比较好用的护眼台灯?央视公认最好的护眼台灯推荐

写这篇文章的时候&#xff0c;我总有种悔不当初的痛感&#xff1a;上学时只喜欢造型好看的台灯&#xff0c;总是把老妈买的护眼灯丢在一边&#xff0c;导致现在眼睛高度近视。虽然不念书了&#xff0c;但平日使用电脑浏览信息、阅读纸质书仍是抛弃不掉的生活习惯&#xff0c;配…

Redis实现方式开启新篇章,解决分布式环境下的资源竞争问题,提升系统稳定性

前言 分布式锁一般有三种实现方式&#xff1a; 数据库乐观锁&#xff1b;基于Redis的分布式锁&#xff1b;基于ZooKeeper的分布式锁 本篇博客将介绍第二种方式&#xff0c;基于Redis实现分布式锁。 虽然网上已经有各种介绍Redis分布式锁实现的博客&#xff0c;然而他们的实…

万字长文搞懂产品模式和项目模式

项目模式是很多传统企业对IT进行投资的方式&#xff0c;相对于产品模式&#xff0c;项目模式在团队建设、快速反应等方面存在很多弊端&#xff0c;本文从多个角度比较了产品和项目两种团队模式的利弊&#xff0c;并在最后回答了若干常见问题。原文: Products Over Projects 软件…

活动回顾|KCD 2023 杭州站

KCD 2023 活动介绍 HANGZHOU 关于 KCD Kubernetes Community Days&#xff08;KCD&#xff09;由云原生计算基金会&#xff08;CNCF&#xff09;发起&#xff0c;由全球各国当地的 CNCF 大使、CNCF 员工以及 CNCF 会员单位联合组织。目前 KCD 正在全球各个国家活跃地组织进行中…

nvidia-smi

1、说明 nvidia-smi 是 NVIDIA System Management Interface 的缩写&#xff0c;是 NVIDIA 提供的一个命令行工具&#xff0c;用于查看和管理 NVIDIA GPU 设备的信息。执行这个命令通常可以获取关于系统上安装的 NVIDIA GPU 的实时状态和性能信息。 一般来说&#xff0c;nvid…

内裤洗衣机有用吗?公认好用的四大款内衣洗衣机推荐

内衣目前洗衣机已经成为我们生活中不可缺少的一种电器。这不但可以节约我们的时间&#xff0c;而且能更好地清洗干净贴身衣物&#xff0c;使我们的生活变得更健康。那么到底哪些内衣洗衣机值得买呢&#xff1f;哪些内衣洗衣机清洗效果会更干净呢&#xff1f;这次&#xff0c;我…

众和策略:谷歌大跌!土耳其股市,两度熔断!

当地时间周三&#xff0c;美股三大指数团体收跌&#xff0c;谷歌等大型科技股连累纳指大跌超2%&#xff0c;创2月以来最大单日跌幅。 当日&#xff0c;谷歌股价大跌近10%至三个月低位&#xff0c;市值一夜蒸发超1600亿美元。周二盘后&#xff0c;谷歌母公司Alphabet发布了最新…

FinalShell或者XShell工具 突然连不上服务器(绝对好使!)

关闭网络管理器 systemctl stop NetworkManager禁止网络管理器开机重启 systemctl disable NetworkManager重启网络 service network restart绝对好使&#xff01;

技术实力获行业高度认可,几何伙伴首获科技进步奖殊荣!

2023年10月25日&#xff0c;“2023年度中国汽车工程学会科学技术奖”正式公布并于北京举行颁奖典礼&#xff0c;以对汽车工业努力奋斗、勇于创新的优秀企业和人才进行嘉奖&#xff0c;对优秀先进成果进行表彰。 其中&#xff0c;由几何伙伴主导&#xff0c;携手上汽集团、友道智…

睿趣科技:抖音小店在哪里选品

随着抖音平台的日益火爆&#xff0c;越来越多的商家选择在抖音小店开设自己的店铺。然而&#xff0c;对于许多新手来说&#xff0c;如何选品却成为了一个难题。那么&#xff0c;抖音小店应该在哪里选品呢? 首先&#xff0c;我们可以从抖音平台上的热门商品入手。通过观察抖音上…

创业酵母:为创业酵母的新增长,数字化“发酵”

成立于2014年11月的创业酵母是一家以教育和咨询为核心的一站式企业服务平台。 张丽俊&#xff08;Cherry&#xff09;和俞朝翎&#xff08;俞头&#xff09;是创业酵母的两位创始人&#xff0c;由于两位创始人都是第一代阿里人&#xff0c;他们希望能将自己在阿里沉淀下来的经验…

NPDP产品经理证书是什么行业的证书?

NPDP是一个跨行业的证书&#xff0c;它适用于各种不同类型和规模的组织。无论是制造业、服务业还是科技领域&#xff0c;都可以从NPDP认证中获益。 1. 制造业&#xff1a; 制造业涉及大量的产品开发和创新活动。从汽车制造到电子设备制造&#xff0c;从家居用品到航天航空&…

重复性管理--抽象的重要性(上)

Haskell 语言的设计者之一 Paul Hudak 曾说过一句略带夸张的话(overstatement): 编程中最重要的三件事是: 抽象, 抽象, 抽象. “abstraction, abstraction, abstraction” are the three most important things in programming. 如果你去问一些资深开发者, 程序员最重要的的能力…

电商API接口教程|设计一个牛逼的Java API接口?

主要从以上三个方面来设计一个安全的电商API接口&#xff08;包含淘宝/天猫/京东/拼多多/抖音/跨境电商亚马逊/阿里巴巴/LAZADA等&#xff09;。 一 安全性问题 安全性问题是一个接口必须要保证的规范。如果接口保证不了安全性&#xff0c;那么你的接口相当于直接暴露在公网环…

vue3+klinecharts实现k线(附完整代码)

vue3klinecharts实现k线 环境安装图表配置创建一个容器实现点击时间切换图表完整代码 环境 vue3 klinecharts 最终实现 安装 npm install klinecharts图表配置 具体可用参考官网 https://klinecharts.com/guide/styles.html const option {crosshair: {show: true,//…

操作系统进程调度算法的模拟实现(c语言版本)

前言&#xff1a;本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现&#xff0c;以及算法描述的讲解&#xff0c;完整代码放在文章末尾&#xff0c;欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路&#xff1a; …