uni-app,关于 canvas 在 app,小程序, h5中,实现绘制,保存本地图片

没有套路,没有难读的文档,直接看代码

html部分

<template>
	<!-- #ifdef MP-WEIXIN -->
		<!-- 定义小程序元素,设置宽高自行设置, type 和 id -->
		<canvas type="2d" id="myCanvas" />
	<!-- #endif -->
	
	<!-- #ifdef APP-PLUS || H5 -->
		<!-- 定义 app 和 h5 元素, 设置宽高自行设置, canvas-id 和 id -->
		<canvas canvas-id="myCanvas" id="myCanvas"></canvas>
	<!-- #endif -->
	
	<button @click="drawCanvas">绘制canvas</button>
	<button @click="preservation">保存到本地</button>
</template>

js部分

<script>
	export default {
    
    
		data() {
    
    
			return {
    
    
				textCanvas: null,		// 初始化 canvas 值
			}
		},
		methods: {
    
    
			// 绘制canvas
			drawCanvas() {
    
    
				// 指定this的指向
				let that = this;
				// uni-app 中,不管是小程序,app,h5 在获取元素实例时,都是统一的方法,只要获取元素的宽高
				uni.createSelectorQuery().select('#myCanvas').fields({
    
     node: true, size: true })
				.exec((res) => {
    
    
					// #ifdef MP-WEIXIN
						// 获取设备设备像素比
						const dpr = uni.getSystemInfoSync().pixelRatio;
						// 微信小程序绘制
						let textCanvas = that.textCanvas = res[0].node;			// 获取元素实例
						textCanvas.width = res[0].width * dpr;					// 设置canvas像素宽
						textCanvas.height = res[0].height * dpr;				// 设置canvas像素高
						let textCtx = textCanvas.getContext('2d');				// 创建二维绘图
						textCtx.clearRect(0, 0, res[0].width, res[0].height);	// 设置画布大小
						textCtx.beginPath();									// 创建一条新的路劲
						textCtx.scale(dpr, dpr);								// 设置x,y缩放(这里作用不大,,没效果)
						
						// 这里开始绘制canvas内容,绘制的过程当中,不知道是小程序的问题,还是什么问题在绘制有背景图片的内容时,
						// 文字内容必须要延迟绘制,也就是要定时器延迟一定时间才能绘制,要不然就会将文字覆盖在图片下方。
						// 图片的绘制
						const tx = textCanvas.createImage();
						tx.src = "../../..";									// 线上地址或者本地地址都可以
						tx.onload = () => {
    
    
							textCtx.drawImage(tx, 20, 20, 100, 100);			// 参数从左到右说明, 图片文件,x轴开始位置,y轴开始位置,x轴结束位置,y轴结束位置
						};
						// 文字设置
						textCtx.fillStyle = "#3085FC";							// 文字颜色
						textCtx.font = "14px sans-serif";						// 字体样式 设置加粗("normal bold 16px sans-serif");
						textCtx.fillText("内容", 160, 45);				        // 设置文字内容, x轴位置,y轴位置

						// 设置分割线
						textCtx.moveTo(10, 130);								// 设置线条开始位置x,y
						textCtx.lineTo(res[0].width - 10, 130);					// 设置线条结束位置x,y
						textCtx.lineWidth = 1;									// 设置线条粗细
						textCtx.strokeStyle = "#e7e7e7";						// 设置线条颜色
						textCtx.stroke();										// 重点,不写线条不显示
						// ... // 其他设置自己查文档很简单
					// #endif
					// #ifdef APP-PLUS || H5
						// app 和 h5 的设置方式是一样的
						let tcx = uni.createCanvasContext('myCanvas');			// 通过canvasId 创建画布
						// 设置图片,如果是背景图,就通过获取的实例,获取到他的宽高直接使用
						tcx.drawImage('../../../static/imgage/abc.png', 0, 0, res[0].width, res[0].height);
						// 文字和分割线设置和小程序无异
						tcx.draw();												// 将设置的内容绘制出来,不写不显示
					// #endif
				})
			},
			// 保存canvas 到本地
			preservation() {
    
    
				// 指定 this 指向
				let that = this;
				// #ifdef MP-WEIXIN
					// 在微信中保存canvas为图片到本地,要通过canvas 实例的参数进行设置
					wx.canvasToTempFilePath({
    
    
						x: 0,
						y: 0,
						width: that.textCanvas.width,							// 设置画布宽度
						height: that.textCanvas.height,							// 设置画布高度
						destWidth: that.textCanvas.width,						// 屏幕width像素密度设置
						destHeight: that.textCanvas.height,						// 屏幕height像素密度设置
						canvas:  that.textCanvas,								// 这里是重点,获取实例的时候保存为全局变量就行了
						complete(res) {
    
    
							// res.tempFilePath 返回的是临时地址 png 或者 jpg
							wx.saveImageToPhotosAlbum({
    
    
								filePath: res.tempFilePath,
								success() {
    
    
									uni.showToast({
    
    
										title: "保存成功",
										icon: "success"
									})
								},
								fail() {
    
    
									uni.showToast({
    
    
										title: "保存失败",
										icon: "error"
									})
								}
							});
						}
					})
				// #endif
				// #ifdef APP-PLUS || H5
					// app 和 h5 获取元素的方式都相同
					uni.canvasToTempFilePath({
    
    
						canvasId: "myCanvas",
						complete(res) {
    
    
							// #ifdef APP-PLUS
								// 在 app 中, 图片地址直接返回的值 临时地址  png 或 jpg,直接使用uni的方法
								uni.saveImageToPhotosAlbum({
    
    
									filePath: res.tempFilePath,
									success() {
    
    
										uni.showToast({
    
    
											title: "保存成功",
											icon: "success"
										});
									},
									fail() {
    
    
										uni.showToast({
    
    
											title: "保存失败",
											icon: "error"
										})
									}
								})
							// #endif
							// #ifdef H5
								// 在 h5 中,res.tempFilePath 返回的是 base64 类型要处理,通过 a 标签的形式下载
								var arr = res.tempFilePath.split(',');
								var bytes = atob(arr[1]);
								let ab = new ArrayBuffer(bytes.length);
								let ia = new Uint8Array(ab);
								for (let i = 0; i < bytes.length; i++) {
    
    
									ia[i] = bytes.charCodeAt(i);
								}
								var blob = new Blob([ab], {
    
     type: 'application/octet-stream' });
								var url = URL.createObjectURL(blob);
								var a = document.createElement('a');
								a.href = url;
								a.download = new Date().valueOf() + ".png";
								var e = document.createEvent('MouseEvents');
								e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
								a.dispatchEvent(e);
								URL.revokeObjectURL(url);							
							// #endif
						}
					})
			}
		}
	}
</script>

猜你喜欢

转载自blog.csdn.net/weixin_44244230/article/details/128082660