uni-app微信小程序-利用canvas给图片添加水印

这篇具有很好参考价值的文章主要介绍了uni-app微信小程序-利用canvas给图片添加水印。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实现思路

选择图片 → 将图片绘制到 canvas 中并绘制水印 →将添加水印的图片绘制到 canvas 中 → 将 canvas 画布转换为图片地址 → 上传/展示操作

一、选择图片

注意:微信小程序在选择照片或者唤起相机之前需要获取相应的 权限

  1. 利用 uni.getSetting 查看用户是否调用相机的权限(有就选择图片,没有就获取授权后再选择图片)
    uni.getSetting({
    	success: async (res) => {
    		// 是否有相机权限
    		if (!res.authSetting['scope.camera']) {
    			// 获取相机权限
    			uni.authorize({
    				scope: 'scope.camera',
    				async success() {
    					// 选择图片
    					chooseImage()
    				}
    			})
    		} else {
    			// 选择图片
    			chooseImage()
    		}
    	},
    	fail(err) {
    		console.log('err :>> ', err);
    	}
    })
    
  2. 利用 uni.chooseMedia 选择图片
    uni.chooseMedia({
    	count: 1, // 1就是最多选择一张图片
    	mediaType: ['image'],
    	sourceType: _this.sourceType, // album相册、camera相机
    	success: async (res) => {
    		const tempFilePath = res.tempFiles[0].tempFilePath
    		//添加水印
    		_this.addWaterMarking(tempFilePath)
    	}
    })
    

二、将图片绘制到 canvas 中并绘制水印

  1. 放置 canvas 画布并将其放置到窗口外

    <template>
    	<view class='waterMarkingCamera'>
    		<canvas id="myCanvas" type="2d" :style="'position:fixed;left:8888px'" />
    	</view>
    </template>
    
  2. 利用 uni.getImageInfo 获取原图片信息

    addWaterMarking(imageUrl) {
    	//获取原图片信息
    	uni.getImageInfo({
    		src: imageUrl,
    		success: async function(res) {
    			const imgWidth = res.width; // 图片的宽
    			const imgHeight = res.height; // 图片的高
    		}
    	})
    }
    
  3. 利用 wx.createSelectorQuery 获取 canvas 对象并渲染上下文

    addWaterMarking(imageUrl) {
    	//获取原图片信息
    	uni.getImageInfo({
    		src: imageUrl,
    		success: async function(res) {
    			const imgWidth = res.width; // 图片的宽
    			const imgHeight = res.height; // 图片的高
    			// 获取 canvas 
    			wx.createSelectorQuery()
    				.in(_this)
    				.select('#myCanvas') // <canvas id="myCanvas" type="2d"  :style="'position:fixed;left:8888px'" />
    				.fields({
    					node: true,
    					size: true
    				})
    				.exec((resCanvas) => {
    					// canvas 对象
    					const canvas = resCanvas[0].node
    					// 初始化画布大小
    					canvas.width = imgWidth;
    					canvas.height = imgHeight;
    					// 渲染上下文
    					const ctx = canvas.getContext('2d')
    				}
    		}
    	})
    }
    
  4. 创建图片对象并绘制图片和水印

    addWaterMarking(imageUrl) {
    	//获取原图片信息
    	uni.getImageInfo({
    		src: imageUrl,
    		success: async function(res) {
    			const imgWidth = res.width; // 图片的宽
    			const imgHeight = res.height; // 图片的高
    			// 获取 canvas 
    			wx.createSelectorQuery()
    				.in(_this)
    				.select('#myCanvas') // <canvas id="myCanvas" type="2d"  :style="'position:fixed;left:8888px'" />
    				.fields({
    					node: true,
    					size: true
    				})
    				.exec((resCanvas) => {
    					// canvas 对象
    					const canvas = resCanvas[0].node
    					// 初始化画布大小
    					canvas.width = imgWidth;
    					canvas.height = imgHeight;
    					// 渲染上下文
    					const ctx = canvas.getContext('2d')
    					// 图片对象
    					const image = canvas.createImage()
    					// 图片加载完成回调
    					image.onload = async () => {
    						let waterMarkingText = _this.waterMarkingText;
    						// 将图片绘制到 canvas 上
    						ctx.drawImage(image, 0, 0, imgWidth, imgHeight)
    						// 添加遮罩水印
    						if (_this.isOverlay) {
    							_this.addOverlay(ctx, res, waterMarkingText)
    						}
    						// 添加文字水印
    						if (typeDetection.call(waterMarkingText) == '[object Array]') {// 判断是否添加多条水印
    							for (let i = 0; i < waterMarkingText.length; i++) {
    								// 设置水印内容
    								const text = waterMarkingText[i] == 'time' ? 
    								_this.$parseTime(new Date()) :
    								waterMarkingText[i] == 'address' ?
    								_this.address : waterMarkingText[i]
    								// 设置水印颜色
    								ctx.fillStyle = typeDetection.call(_this.fontColor) == '[object Array]' ?
    								_this.fontColor[i] : _this.fontColor;
    								// 设置水印文字大小
    								ctx.font = `${typeDetection.call(_this.fontSize) == '[object Array]' ?
    								_this.fontSize[i] : _this.fontSize}px arial`;
    								// 绘制水印文字
    								ctx.fillText(text, _this.interval[0], res.height - 
    								(typeDetection.call(_this.fontSize) == '[object Array]' ?
    								 _this.fontSize[i] : 
    								_this.fontSize) - _this.interval[1] * i)
    								ctx.restore();
    							}
    						} else {
    							// 设置水印颜色
    							ctx.fillStyle = _this.fontColor;
    							// 设置水印文字大小
    							ctx.font = `${_this.fontSize}px arial`;
    							// 绘制水印文字
    							ctx.fillText(waterMarkingText, _this.interval[0], res.height -  _this.fontSize);
    							ctx.restore();
    						}
    					}
    					image.src = imageUrl
    				})
    		}
    	})
    }
    

三、将 canvas 画布转换为图片地址

	addWaterMarking(imageUrl) {
		//获取原图片信息
		uni.getImageInfo({
			src: imageUrl,
			success: async function(res) {
				const imgWidth = res.width; // 图片的宽
				const imgHeight = res.height; // 图片的高
				// 获取 canvas 
				wx.createSelectorQuery()
					.in(_this)
					.select('#myCanvas') // <canvas id="myCanvas" type="2d"  :style="'position:fixed;left:8888px'" />
					.fields({
						node: true,
						size: true
					})
					.exec((resCanvas) => {
						// canvas 对象
						const canvas = resCanvas[0].node
						// 初始化画布大小
						canvas.width = imgWidth;
						canvas.height = imgHeight;
						// 渲染上下文
						const ctx = canvas.getContext('2d')
						// 图片对象
						const image = canvas.createImage()
						// 图片加载完成回调
						image.onload = async () => {
							let waterMarkingText = _this.waterMarkingText;
							// 将图片绘制到 canvas 上
							ctx.drawImage(image, 0, 0, imgWidth, imgHeight)
							// 添加遮罩水印
							if (_this.isOverlay) {
								_this.addOverlay(ctx, res, waterMarkingText)
							}
							// 添加文字水印
							if (typeDetection.call(waterMarkingText) == '[object Array]') {
								for (let i = 0; i < waterMarkingText.length; i++) {
									// 设置水印内容
									const text = waterMarkingText[i] == 'time' ? 
									_this.$parseTime(new Date()) :
									waterMarkingText[i] == 'address' ?
									_this.address : waterMarkingText[i]
									// 设置水印颜色
									ctx.fillStyle = typeDetection.call(_this.fontColor) == '[object Array]' ?
									_this.fontColor[i] : _this.fontColor;
									// 设置水印文字大小
									ctx.font = `${typeDetection.call(_this.fontSize) == '[object Array]' ?
									_this.fontSize[i] : _this.fontSize}px arial`;
									// 绘制水印文字
									ctx.fillText(text, _this.interval[0], res.height - 
									(typeDetection.call(_this.fontSize) == '[object Array]' ?
									 _this.fontSize[i] : 
									_this.fontSize) - _this.interval[1] * i)
									ctx.restore();
								}
							} else {
								// 设置水印颜色
								ctx.fillStyle = _this.fontColor;
								// 设置水印文字大小
								ctx.font = `${_this.fontSize}px arial`;
								// 绘制水印文字
								ctx.fillText(waterMarkingText, _this.interval[0], res.height -  _this.fontSize);
								ctx.restore();
							}
							// 某些平台 canvas 绘制比较慢,需要等待绘制完成
							await _this.sleep(500)
							// 将 canvas 画布转换为图片地址
							wx.canvasToTempFilePath({
								canvas: canvas,
								async success(res) {
								// 上传图片操作
								await _this.uploadImage(res.tempFilePath)
								}
							})
						}
						image.src = imageUrl
					})
			}
		})
	}

四、最终效果

uniapp 小程序canvas,uni-app / 小程序,uni-app,微信小程序文章来源地址https://www.toymoban.com/news/detail-738533.html

五、完整代码

<template>
	<view class='waterMarkingCamera'>
		<canvas id="myCanvas" type="2d" :style="'position:fixed;left:8888px'" />
		<view class="waterMarkingCamera-icon" @tap='handleChooseImage()' v-show="!imageArr||imageArr.length<limit">
			<slot name="W_M_C_Icon">
				<text class="iconfont icon-a-xiangji"></text>
			</slot>
		</view>
	</view>
</template>
<script>
	var typeDetection = Object.prototype.toString;
	export default {
		name: 'waterMarkingCamera',
		/**	
		 *	waterMarkingCamera 水印相机
		 *	@property {Array} attachmentList 附件列表
		 * 	@property {Array} sourceType 数据源类型 album(相册) camera(相机)
		 * 	@property {Number|String} limit 限制照片数 999
		 * 	@property {Boolean} isOverlay 是否需要遮罩 true
		 * 	@property {Array|String} waterMarkingText 水印文字 ['time','address'] ['水印文字',水印文字2] | '水印文字' time(添加时间)、address(添加地址)
		 * 	@property {Array|String} fontSize 水印文字大小 32 ['32',100] | '32'
		 * 	@property {Array|String} fontColor 水印文字颜色 '#ffffff' ['#ffffff','red','rgba(255, 255, 255,0.2)','rgb(255, 255, 255)'] | '#ffffff'
		 * 	@property {Array} interval 间距 [50, 80]
		 * 
		 * */
		props: {
			attachmentList: {
				type: Array,
				default: () => {
					return []
				}
			},
			sourceType: {
				type: Array,
				default: () => {
					return ['album', 'camera']
				}
			},
			limit: {
				type: [Number, String],
				default: 999
			},
			isOverlay: {
				type: Boolean,
				default: true
			},
			waterMarkingText: {
				type: [Array, String],
				default: () => {
					return ['time', 'address']
				}
			},
			fontSize: {
				type: [Array, Number, String],
				default: 32
			},
			fontColor: {
				type: [Array, String],
				default: '#ffffff'
			},
			interval: {
				type: Array,
				default: () => {
					return [50, 50]
				}
			}
		},
		data() {
			return {
				imageArr: [],
				address: '你的位置信息'
			}
		},
		mounted() {
			this.imageArr = this.attachmentList
			// 反转内容数组
			if (typeDetection.call(this.waterMarkingText) ==
				'[object Array]') {
				this.waterMarkingText.reverse()
			}
		},
		methods: {
			// 选择照片
			handleChooseImage() {
				let _this = this
				uni.getSetting({
					success: async (res) => {
						const chooseImage = () => {
							uni.chooseMedia({
								count: 1, // 最多选择一张图片
								mediaType: ['image'],
								sourceType: _this.sourceType, // 相册、相机
								success: async (res) => {
									const tempFilePath = res.tempFiles[0].tempFilePath
									_this.addWaterMarking(tempFilePath)
								}
							})
						}
						// 是否有相机权限
						if (!res.authSetting['scope.camera']) {
							// 获取相机权限
							uni.authorize({
								scope: 'scope.camera',
								async success() {
									// 选择照片
									chooseImage()
								}
							})
						} else {
							// 选择照片
							chooseImage()
						}
					},
					fail(err) {
						console.log('err :>> ', err);
					}
				})
			},
			// 添加水印
			addWaterMarking(imageUrl) {
				uni.showLoading({
					title: '上传中...',
					mask: true
				})
				var _this = this;
				//获取原图片信息
				uni.getImageInfo({
					src: imageUrl,
					success: async function(res) {
						const imgWidth = res.width; // 图片的宽
						const imgHeight = res.height; // 图片的高
						// 获取canvas 
						wx.createSelectorQuery()
							.in(_this)
							.select('#myCanvas') // 在 WXML 中填入的 id
							.fields({
								node: true,
								size: true
							})
							.exec((resCanvas) => {
								// Canvas 对象
								const canvas = resCanvas[0].node
								// 初始化画布大小
								canvas.width = imgWidth;
								canvas.height = imgHeight;
								// 渲染上下文
								const ctx = canvas.getContext('2d')
								// 图片对象
								const image = canvas.createImage()
								// 图片加载完成回调
								image.onload = async () => {
									let waterMarkingText = _this.waterMarkingText;
									// 将图片绘制到 canvas 上
									ctx.drawImage(image, 0, 0, imgWidth, imgHeight)
									// 添加遮罩水印
									if (_this.isOverlay) {
										_this.addOverlay(ctx, res, waterMarkingText)
									}
									// 添加文字水印
									if (typeDetection.call(waterMarkingText) ==
										'[object Array]') {
										for (let i = 0; i < waterMarkingText.length; i++) {
											// 设置水印内容
											const text = waterMarkingText[i] == 'time' ?
												_this.$parseTime(new Date()) :
												waterMarkingText[i] ==
												'address' ?
												_this.address : waterMarkingText[i]
											// 设置水印颜色
											ctx.fillStyle = typeDetection.call(_this.fontColor) ==
												'[object Array]' ?
												_this.fontColor[i] : _this.fontColor;
											// 设置水印文字大小
											ctx.font = `${typeDetection.call(_this.fontSize) ==
												'[object Array]' ?
												_this.fontSize[i] : _this.fontSize}px arial`;
											// 绘制水印文字
											ctx.fillText(text, _this.interval[0], res.height - (
													typeDetection
													.call(_this
														.fontSize) == '[object Array]' ?
													_this.fontSize[i] : _this.fontSize) - _this
												.interval[1] * i)
											ctx.restore();
										}
									} else {
										// 设置水印颜色
										ctx.fillStyle = _this.fontColor;
										// 设置水印文字大小
										ctx.font = `${_this.fontSize}px arial`;
										// 绘制水印文字
										ctx.fillText(waterMarkingText, _this.interval[0], res
											.height -
											_this
											.fontSize);
										ctx.restore();
									}
									// 某些平台 canvas 绘制比较慢,需要等待绘制完成
									await _this.sleep(500)
									// 将 canvas 画布转换为图片地址
									wx.canvasToTempFilePath({
										canvas: canvas,
										async success(res) {
											// 上传图片操作
										}
									})
								}
								image.src = imageUrl
							})
					}
				})
				this.handleEmit()
			},
			// 添加遮罩
			addOverlay(ctx, res, waterMarkingText) {
				let makerHeight = 0
				if (typeDetection.call(this.fontSize) ==
					'[object Array]') {
					for (let i = 0; i < this.fontSize; i++) {
						makerHeight += (this.fontSize[i] + this
							.interval[1])
					}
				} else {
					makerHeight += (this.fontSize * waterMarkingText.length + this
						.interval[1] * (waterMarkingText.length - 1))
				}
				ctx.rect(0, res.height - makerHeight, res.width, makerHeight);
				ctx.fillStyle = "rgba(46, 46, 46,0.4)";
				ctx.fill();
			},
			// 触发emit
			handleEmit() {
				this.$emit('change', this.imageArr)
				this.$emit('input', this.imageArr)
				this.$emit('update:modelValue', this.imageArr)
			},
			sleep(millisecond) {
				return new Promise((resolve) => {
					setTimeout(resolve, millisecond)
				})
			}
		}
	}
</script>
<style lang="scss" scoped>
	.waterMarkingCamera {
		display: flex;
		flex-flow: row;
		align-items: center;
		justify-content: flex-end;
		padding: 20rpx 0;

		&-icon {
			width: 146rpx;
			height: 120rpx;
			border-radius: 4rpx;
			font-size: 42rpx;
			text-align: center;
			line-height: 108rpx;
			border: 2rpx dashed #666666;
		}
	}
</style>

到了这里,关于uni-app微信小程序-利用canvas给图片添加水印的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uni-app 微信小程序 保存当前页面为图片

    由于在微信小程序环境下面没法获取dom,很多方法都很难去实现保存html结构的页面,比较有效的#painter 可以不需要操作dom,但是那玩意儿和重新用js写个页面一样,简单的页面还好,复杂的,元素比较多的就很麻烦,所以考虑用webview+html2canvas来完成 先说一下思路,既然在微

    2024年02月11日
    浏览(38)
  • 微信小程序给图片加水印【使用uni-app】

    选择图片后使用canvas绘制图片,再绘制需要的水印文字,将绘制好的画布转化为图片即可 最终效果

    2024年02月10日
    浏览(36)
  • uni-app/微信小程序 实现图片或元素淡入淡出效果

    如题: 直接上代码 html js部分 需要在date中声明好                 current: 0,                 hidepic: null,                 showpic: null 因为是已进入就开始的,所以 要在生命周期中使用 最后一部别忘了,要给需要淡入淡出的元素或者图片设置绝对定位

    2024年02月12日
    浏览(46)
  • 微信小程序uni-app图片和base64相互转换

    以上代码仅供参考,具体实现细节和样式可以根据需求自行调整。 需要完整源码的朋友,希望你能点赞+收藏+评论,然后私信我即可~ 如果教程中有不懂的地方,可添加学习会员小助手咨询(微信:mifankeji77)

    2024年02月14日
    浏览(32)
  • uni-app(微信小程序)图片旋转放缩,文字绘制、海报绘制

    总结一下: 要进行海报绘制离不开canvas,我们是先进行图片,文字的拖拽、旋转等操作 最后再对canvas进行绘制,完成海报绘制。 背景区域设置为 position: relative,方便图片在当前区域中拖动等处理。 添加图片,监听图片在背景区域下的 touchstart touchmove touchend 事件 拖动图片,

    2024年02月09日
    浏览(40)
  • uni-app:使用 Painter 在微信小程序将当前页面保存为图片

    手机截屏 Painter 实现 方式一:Painter Painter 是一个微信小程序组件,具体介绍和 API 请参考:GitHub文档。 在 GitHub 下载下来之后只需要将 components 下的 painter 文件夹放到项目根目录下的 wxcomponents 文件夹即可。然后就是如何在 uni-app 中使用微信小程序形式的组件,其实很简单,

    2024年02月12日
    浏览(45)
  • 【微信小程序】如何获得自己当前的定位呢?本文利用逆地址解析、uni-app带你实现

    目录 前言 效果展示 一、在腾讯定位服务配置微信小程序JavaScript SDK 二、使用uni-app获取定位的经纬度 三、 逆地址解析,获取精确定位 四、小提示 在浏览器搜索腾讯定位服务,找到官方网站,利用微信或者其他账号注册登录,登录后如下图操作 点进去之后,可以看到如下图

    2024年01月19日
    浏览(63)
  • uni-app,关于 canvas 在 app,小程序, h5中,实现绘制,保存本地图片

    没有套路,没有难读的文档,直接看代码 html部分 js部分

    2024年02月13日
    浏览(34)
  • uni-app uni-file-picker文件上传实现拍摄从相册选择获取图片上传文档服务器(H5上传-微信小程序上传)

    前言 最近在使用uni-app写H5移动端,有一个从手机拍摄从相册选择获取图片上传到文档服务器功能。 查阅uni-app发现关于上传图片,uni-file-picker文件上传,uni.chooseImage,uni.uploadFile H5上传时它和pc端原理差不多,都是file对象上传,PC端是通过new file对象,uni-app是直接提供了 微信

    2024年02月15日
    浏览(41)
  • uni-app实现canvas绘制图片、海报等

    前段时间有个项目,需要绘制海报,我一听这不是可以用canvas来实现吗,所以我在五一假期就记录下实现方式 我把canvas绘制图片封装成一个组件,直接引入使用就好了。 这里虽然是uni-app写的,但实现方式其实都是一样的,之后其他原生小程序用到也是大差不大的,真的很简

    2024年02月09日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包