uniapp图片加水印

1、uniapp加水印

1.1、创建画布容器

<canvas class="watermark-canvas" id="watermark-canvas" canvas-id="watermark-canvas"
			:style="{ width: canvasWidth, height: canvasHeight }" />

1.2、获取水印内容

async getLocation() {
				const zero = (item) => item < 10 ? "0" + item : item

				const time = new Date();
				const yy = time.getFullYear();
				const mm = time.getMonth() + 1;
				const dd = time.getDay();
				const hh = time.getHours();
				const MM = time.getMinutes();
				const ww = time.getDay()

				const hm = zero(hh) + ':' + zero(MM)
				const ymd = yy + '-' + zero(mm) + '-' + zero(dd)

				const {
					name: location
				} = await this.$store.dispatch('location/juGetLocation')

				return {
					hm,
					ymd,
					address: location
				}
			},

1.3、添加水印上传图片

async chooseImage(e) {
				// #ifdef APP-PLUS
				let status = await this.checkPermission()
				if (status !== 1) {
					return
				}
				// }

				// #endif
				uni.chooseImage({
					sourceType: sourceType[this.sourceTypeIndex],
					sizeType: ['compressed'],
					count: this.limit,
					success: async (res) => {
						let filePath = res.tempFilePaths[0]
						const watermark = await this.getLocation()
//压缩图片设置宽度,不然画不全
						uni.compressImage({
							src: filePath,
							quality: 80,
							success: async comres => {
								//绘制图片加水印
								let img = await this.fillTextToImg(comres.tempFilePath, watermark)
								uni.showLoading({
									title: '上传中...',
									mask: true
								})
								const arr = [img]
								// 上传图片
								const key = await this.$store.dispatch('upload/uploadFileList', arr)
								this.$emit('handleChangeKeys', {
									src: key,
									create_time: watermark.hm,
									sign_date: watermark.ymd,
									sign_local: watermark.address
								})

								uni.hideLoading()
							}
						})

					},

					fail: (err) => {}
				})
			},
			sleep(millisecond) {
				return new Promise((resolve) => {
					setTimeout(resolve, millisecond)
				})
			},
			fillTextToImg(file, watermark) {
				return new Promise((resolve, reject) => {
					uni.getImageInfo({
						src: file,
						success: async res => {
//设置画布大小,然后再画,不然会只画一部分
							this.canvasWidth = `${res.width}px`
							this.canvasHeight = `${res.height}px`
							await this.sleep(200)
							const ctx = uni.createCanvasContext('watermark-canvas', this)
							ctx.clearRect(0, 0, res.width, res.height)
							ctx.beginPath()
							ctx.drawImage(res.path, 0, 0, res.width, res.height)
							// 水印 字体大小,颜色,内容,位置
							ctx.beginPath()
							ctx.setFillStyle('#ffffff')
							const fontSize = res.width / 10
							ctx.setFontSize(fontSize)
							ctx.fillText(watermark.hm, res.width / 2 - res.width / 8, res.height / 2 - 50)
							ctx.setFontSize(res.width / 15)
							ctx.fillText(watermark.ymd, res.width / 2 - res.width / 6, res.height / 2 + 100)
							ctx.setFontSize(res.width / 17)
							ctx.fillText(watermark.address, res.width / 5 - 15, res.height / 1.5 + 50)
							// 开始绘制 (canvas -> 临时文件路径)
							ctx.draw(false, async () => {
								await this.sleep(500) // 某些平台 canvas 渲染慢,需要等待

								uni.canvasToTempFilePath({
										canvasId: 'watermark-canvas',
										destWidth: res.width,
										destHeight: res.height,
										fileType: 'jpg',
										quality: 0.8,
										success: (fileRes) => {
											resolve(fileRes.tempFilePath)
										},
										fail: (err) => {
											uni.showToast({
												title: err.errMsg,
												icon: 'none'
											})
											reject()
										},
									},
									this,
								)
							})
						},
						fail: (err) => {
							console.log('[Error getImageInfo]', err)
							uni.showToast({
								title: err.errMsg,
								icon: 'none'
							})
							reject()
						},
					})
				});
			},

1.4、设置画布位置,不让其显示

.watermark-canvas {
		transform: scale(1);
		transform-origin: 0 0;
		position: absolute;
		top: -999px;
		left: -999px;
	}

2、web端加水印(Image,FileReaderweb端才能使用)

// 获取本地图片的base64编码
// 使用在线图片链接的时候需要注意给图片设置crossOrigin属性
function fileToBase64Async(file) {
	return new Promise((resolve, reject) => {
		let reader = new FileReader();
		reader.readAsDataURL(file);
		reader.onload = (e) => {
			resolve(e.target.result);
		};
	});
}

// fillText绘制的是默认的普通实线文本,strokeText绘制的是描边文本
function fillTextToImg(base64) {
	const img = new Image();
	img.src = base64;
	img.setAttribute("crossOrigin", "Anonymous");
	return new Promise((resolve, reject) => {
		img.onload = () => {
			// 生成一个 canvas 画布;
			const canvas = document.createElement("canvas");
			canvas.width = img.width;
			canvas.height = img.height;
			// 将现有需要添加水印的图片绘制到画布上;
			const ctx = canvas.getContext("2d");
			ctx.fillRect(0, 0, canvas.width, canvas.height);
			ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
			const remFontSize = canvas.width / 35;
			ctx.font = "bolder " + remFontSize + "px Verdana";
			ctx.textAlign = "center";
			/**
			  ctx.textAlign = "center|end|left|right|start";
			  start:默认,文本在指定的位置开始。
			  end:文本在指定的位置结束。
			  center:文本的中心在指定的位置。
			  left:文本左对齐。
			  right:文本右对齐。
			  **/
			ctx.strokeStyle = "#fff";
			const name = "@AAAAAAAAAAAAA";
			const spaceH = remFontSize * 0.3;
			ctx.fillText(
				name,
				canvas.width / 2,
				canvas.height - remFontSize - spaceH
			);
			resolve(canvas.toDataURL("image/jpeg"));
		};
	});
}
相关推荐
不想有bug的小菜鸟1 分钟前
vue3使用iframe全屏展示pdf效果
前端·pdf
m0_748238632 分钟前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端
u0100559603 分钟前
前端代理,解决跨域问题讲解
前端
quitv8 分钟前
react脚手架配置别名
前端·javascript·react.js
m0_5287238117 分钟前
前端如何进行性能优化
前端·性能优化
化作繁星18 分钟前
在 Vue 3 中,如何缓存和复用动态组件
前端·vue.js·缓存
一粒沙-38 分钟前
iOS 将GIF图分享至微信
前端·ios
graywen42 分钟前
从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
前端
Gazer_S2 小时前
【现代前端框架中本地图片资源的处理方案】
前端·javascript·chrome·缓存·前端框架
林的快手4 小时前
CSS默认样式
前端·css·vue.js·chrome·css3