uniapp微信小程序保存海报到手机相册canvas

发布于:2025-09-13 ⋅ 阅读:(16) ⋅ 点赞:(0)

在uniapp中实现微信小程序保存海报到手机相册,主要涉及Canvas绘制和图片保存。以下是关键步骤和代码示例:

一、关键代码展示:
1. 模板配置:页面展示该海报,可直接查看,也可下载保存到手机相册,html关键代码如下:
<view class="content">
	<canvas class="canvas-poster" canvas-id="canvasposter"></canvas>
</view>
2. 海报绘制:js关键代码如下:
//绘制到canvas
downloadQrcode: function() {
	var ctx = uni.createCanvasContext("canvasposter")
	let that = this

	// #ifdef MP-WEIXIN
	uni.downloadFile({
		url: 'https://xxx.zexun.tech/getfile/statics/cdn/images/large_invite_bg.png', // 网络图片链接
		success: downloadResult => {
			if (downloadResult.statusCode === 200) {
				/* 绘制第一张照片*/
				// 参数说明:('图片路径',canvas的横坐标,canvas的纵坐标,图片的宽度,图片的宽度)
				ctx.drawImage(downloadResult.tempFilePath, 0, 0, 750, 1624)

				// 绘制第二张图片-base64-转换真机可读
				wx.getFileSystemManager().writeFile({
					filePath: wx.env.USER_DATA_PATH + "/test.png",
					data: that.codeBase64,
					encoding: 'base64',
					success: (res) => {
						ctx.drawImage(wx.env.USER_DATA_PATH + "/test.png", 164,
							816, 420, 420)
						ctx.setTextAlign("center")
						ctx.setFontSize(34)  // 第一行文字
						ctx.fillStyle = '#2B5370'; // 设置文字颜色为白色
						ctx.fillText('我的邀请码:'+ that.$userInfo.agentNo, 375,
							668) //文字内容、x坐标,y坐标
						ctx.setFontSize(26) // 第二行文字
						ctx.fillStyle = '#636D86'; // 设置文字颜色为白色
						ctx.fillText('扫一扫下方二维码,成为我的业务伙伴', 365,
							782) //文字内容、x坐标,y坐标
						uni.showLoading({
							title: "图片生成中...",
						})
						ctx.draw(
							false,
							setTimeout(() => {
								that.getTempFilePath()
							}, 2500)
						)
					}
				})

			}
		},
		fail: () => {
			uni.showToast({
				title: '下载失败',
				icon: 'none'
			});
		}
	});
	// #endif
},
//获取临时路径
getTempFilePath: function() {
	// 当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
	uni.canvasToTempFilePath({
		canvasId: "canvasposter",
		success: (res) => {
			console.log(res.tempFilePath)
			this.saveImageToPhotosAlbum(res.tempFilePath) //保存到相册
		},
	})
},
//把生成的图片保存至相册
saveImageToPhotosAlbum: function(imgUrl) {
	uni.hideLoading()
	if (imgUrl) {
		uni.saveImageToPhotosAlbum({
			filePath: imgUrl,
			success: (res) => {
				uni.showToast({
					title: "保存成功",
					icon: "success",
					duration: 2000,
				})
			},
			fail: (err) => {
				uni.showToast({
					title: "保存失败",
					icon: "none",
					duration: 2000,
				})
			},
		})
	} else {
		uni.showToast({
			title: "绘制中……",
			icon: "loading",
			duration: 3000,
		})
	}
},
3. 样式css关键代码如下:
/* 绘制图片canvas样式 */
.canvas-poster {
	position: fixed;
	width: 750px;
	height: 1624px;
	top: 100%;
	left: 100%;
}
二、完整代码附录:
<template>
	<view class="content">
		<!-- #ifdef MP-WEIXIN -->
		<view class="guide_header_page2">
			<view :style="{ height: statusBarHeight }"></view>
			<view class="guide_title" :style="{ height: navigationBarHeight, lineHeight:navigationBarHeight  }">
				<uni-icons type="back" size="22" color="#232323" @click="goBack" class="icon"></uni-icons>
				<text>我的邀请码</text>
			</view>
		</view>
		<!-- #endif -->

		<view class="invite">
			<image src="https://xxx.zexun.tech/getfile/statics/cdn/images/large_invite_bg.png" mode="widthFix"
				class="bg" />
			<view class="invite_title">我的邀请码:{{$userInfo.agentNo}}</view>
			<view class="invite_tip">
				扫一扫下方二维码,成为我的业务伙伴
			</view>
			<image :src="'data:image/png;base64,' + codeBase64" mode="widthFix" class="qrcode" />
			<view class="invite_btn">
				<u-button text="保存图片" shape="circle" color="linear-gradient(to right, #26B6B9, #21CE98)" @click="downloadQrcode"></u-button>
			</view>
		</view>
		<canvas class="canvas-poster" canvas-id="canvasposter"></canvas>
	</view>
</template>

<script>
	import {
		getInvitationCode
	} from '@/common/api.js'
	export default {
		data() {
			return {
				// #ifdef MP-WEIXIN
				statusBarHeight: uni.getSystemInfoSync().statusBarHeight + 'px', // 状态栏高度
				capBarHeight: uni.getMenuButtonBoundingClientRect().height + 'px', // 胶囊高度
				navigationBarHeight: (uni.getMenuButtonBoundingClientRect().top - uni.getSystemInfoSync()
					.statusBarHeight) * 2 + uni.getMenuButtonBoundingClientRect().height + 'px', // 导航栏高度
				barCapHeight: (uni.getMenuButtonBoundingClientRect().top - uni.getSystemInfoSync()
						.statusBarHeight) * 2 + uni.getMenuButtonBoundingClientRect().height + uni.getSystemInfoSync()
					.statusBarHeight + 'px', //导航栏高度+状态栏高度
				// #endif
				codeBase64: null,
				type: '2', // 2-服务商邀请码,3-业务员邀请码
			}
		},
		onLoad() {
			this.getInvitationCode()
		},
		methods: {
			goBack() {
				uni.navigateBack()
			},
			// 获取二维码
			getInvitationCode() {
				uni.showLoading({
					mask: true
				})
				getInvitationCode({
						inviteCode: this.$store.state.$userInfo.agentId,
						type: this.type
					})
					.then((res) => {
						uni.hideLoading()
						this.codeBase64 = res.data
					})
					.catch((err) => {
						uni.hideLoading()
						console.log(err)
					})
			},
			//绘制到canvas
			downloadQrcode: function() {
				var ctx = uni.createCanvasContext("canvasposter")
				let that = this

				// #ifdef MP-WEIXIN
				uni.downloadFile({
					url: 'https://xxx.zexun.tech/getfile/statics/cdn/images/large_invite_bg.png', // 网络图片链接
					success: downloadResult => {
						if (downloadResult.statusCode === 200) {
							/* 绘制第一张照片*/
							// 参数说明:('图片路径',canvas的横坐标,canvas的纵坐标,图片的宽度,图片的宽度)
							ctx.drawImage(downloadResult.tempFilePath, 0, 0, 750, 1624)

							// 绘制第二张图片-base64-转换真机可读
							wx.getFileSystemManager().writeFile({
								filePath: wx.env.USER_DATA_PATH + "/test.png",
								data: that.codeBase64,
								encoding: 'base64',
								success: (res) => {
									ctx.drawImage(wx.env.USER_DATA_PATH + "/test.png", 164,
										816, 420, 420)
									ctx.setTextAlign("center")
									ctx.setFontSize(34)  // 第一行文字
									ctx.fillStyle = '#2B5370'; // 设置文字颜色为白色
									ctx.fillText('我的邀请码:'+ that.$userInfo.agentNo, 375,
										668) //文字内容、x坐标,y坐标
									ctx.setFontSize(26) // 第二行文字
									ctx.fillStyle = '#636D86'; // 设置文字颜色为白色
									ctx.fillText('扫一扫下方二维码,成为我的业务伙伴', 365,
										782) //文字内容、x坐标,y坐标
									uni.showLoading({
										title: "图片生成中...",
									})
									ctx.draw(
										false,
										setTimeout(() => {
											that.getTempFilePath()
										}, 2500)
									)
								}
							})

						}
					},
					fail: () => {
						uni.showToast({
							title: '下载失败',
							icon: 'none'
						});
					}
				});
				// #endif


				// #ifndef MP-WEIXIN
				/* 绘制第一张照片*/
				// 参数说明:('图片路径',canvas的横坐标,canvas的纵坐标,图片的宽度,图片的宽度)
				ctx.drawImage("https://jsfzapi.zexun.tech/getfile/statics/cdn/images/invite_bg.png", 0, 0,
					750, 1624)
				/* 绘制第二张照片*/
				ctx.drawImage("data:image/png;base64," + this.codeBase64, 164, 912, 420, 420)
				ctx.setTextAlign("center")
				ctx.setFontSize(32)
				ctx.setTextAlign("center")
				ctx.fillText(this.$realAgentInfo.shortName, 375, 880) //文字内容、x坐标,y坐标
				uni.showLoading({
					title: "图片生成中...",
				})
				ctx.draw(
					false,
					setTimeout(() => {
						this.getTempFilePath()
					}, 1500)
				)
				// #endif
			},
			//获取临时路径
			getTempFilePath: function() {
				// 当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
				uni.canvasToTempFilePath({
					canvasId: "canvasposter",
					success: (res) => {
						console.log(res.tempFilePath)
						this.saveImageToPhotosAlbum(res.tempFilePath) //保存到相册
					},
				})
			},
			//把生成的图片保存至相册
			saveImageToPhotosAlbum: function(imgUrl) {
				uni.hideLoading()
				if (imgUrl) {
					uni.saveImageToPhotosAlbum({
						filePath: imgUrl,
						success: (res) => {
							uni.showToast({
								title: "保存成功",
								icon: "success",
								duration: 2000,
							})
						},
						fail: (err) => {
							uni.showToast({
								title: "保存失败",
								icon: "none",
								duration: 2000,
							})
						},
					})
				} else {
					uni.showToast({
						title: "绘制中……",
						icon: "loading",
						duration: 3000,
					})
				}
			},
		},
	}
</script>

<style lang="scss" scoped>
	/* 绘制图片canvas样式 */
	.canvas-poster {
		position: fixed;
		width: 750px;
		height: 1624px;
		top: 100%;
		left: 100%;
	}

	.content {
		.invite {
			width: 100%;
			position: relative;

			.bg {
				width: 750rpx;
			}

			.invite_title {
				min-width: 418rpx;
				position: absolute;
				left: 52%;
				transform: translateX(-50%);
				top: 630rpx;
				font-weight: bold;
				font-size: 34rpx;
				color: #2B5370;
			}
			
			.invite_tip {
				min-width: 442rpx;
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				top: 766rpx;
				font-weight: 500;
				font-size: 26rpx;
				color: #636D86;
			}

			.qrcode {
				width: 420rpx;
				height: 420rpx;
				left: 50%;
				transform: translateX(-50%);
				top: 830rpx;
				position: absolute;
			}

			.invite_btn {
				width: 484rpx;
				height: 76rpx;
				bottom: 176rpx;
				position: absolute;
				z-index: 999;
				left: 50%;
				transform: translateX(-50%);
			}
		}
	}
</style>
三、效果图展示:

在这里插入图片描述

提示:使用 uni.downloadFile 下载网络图片 https://xxx.xxx 等,需要在小程序后台配置服务器域名;
在这里插入图片描述

有什么疑问,可以评论区回复,大家一起探讨~