直接复制到项目就可以用,废话不多说

<template>
	<view class="main">
<!-- 		<view class="qrcode-wrapper">
			<image class="qrcode-save__image" :src="shareQrcodeUrl" mode="aspectFit"></image>
			<view class="qrcode-save__btn">
				
			</view>
		</view> -->
		<canvas :style="{ width: canvasW + 'px', height: canvasH + 'px',}" canvas-id="myCanvas" id="myCanvas"></canvas>
		<view class="">
			<button text="保存图片" @click="saveShareQrcode">保存图片</button>
		</view>
	</view>
</template>

<script>
	var that
	export default {
		data() {
			return {				
				canvasW:0, // 画布宽
				canvasH:0, // 画布高
				SystemInfo:{}, // 设备信息
				goodsImg: {}, // 商品主图
				ewmImg:{}, // 二维码图片
				ewmW:120, // 二维码大小
				title:'规则规则规则规则规则规则规则规则规则规则规则规则规则规则规则规则规则规则', // 商品标题
				canvasShow:true ,
				shareQrcodeUrl:''//canvas本地路径
			}
		},
		onLoad(options) {
			that = this
			this.createPoster()
		},
		methods: {
			async createPoster(){
				// 获取设备信息,主要获取宽度,赋值给canvasW 也就是宽度:100%
				this.SystemInfo = await this.getSystemInfo();
				// 获取商品主图,二维码信息,APP端会返回图片的本地路径(H5端只能返回原路径)
				this.goodsImg = await this.getImageInfo('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png');
				this.ewmImg = await this.getImageInfo('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png');
				this.canvasW = this.SystemInfo.windowWidth; // 画布宽度
				this.canvasH = this.goodsImg.height + this.ewmW + 200;  // 画布高度 = 主图高度+二维码高度 + 文字图片的间距(大概50)
				
				// 如果主图,二维码图片,设备信息都获取成功,开始绘制海报,这里需要用setTimeout延时绘制,否则可能会出现图片不显示。
				if(this.goodsImg.errMsg == 'getImageInfo:ok' && this.ewmImg.errMsg == 'getImageInfo:ok' && this.SystemInfo.errMsg == 'getSystemInfo:ok'){
					console.log('ok')
					uni.showToast({
						icon:'loading',
						mask:true,
						duration:10000,
						title: '海报绘制中',
					});
					setTimeout(()=>{
						var ctx = uni.createCanvasContext('myCanvas', this);
						// 填充背景色,白色
						ctx.setFillStyle('#fff'); // 默认白色
						ctx.fillRect(0, 0, this.canvasW, this.canvasH) // fillRect(x,y,宽度,高度)
						
						// 绘制商品主图,二维码
						ctx.drawImage(this.goodsImg.path, 0, 0, this.canvasW, this.canvasW) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
						ctx.drawImage(this.ewmImg.path, 20, this.canvasW+60, this.ewmW, this.ewmW) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度,二维码的宽,高)
						
						// 3、绘制商品标题,多余文字自动换行
						ctx.setFontSize(16); // setFontSize() 设置字体字号
						ctx.setFillStyle('#333'); // setFillStyle() 设置字体颜色
						
						/* str 这段代码是我百度找的,参考别人的。canvas不能自动换行,需要自行计算 */
						let _strlineW = 0;
						let _strLastIndex = 0; //每次开始截取的字符串的索引
						let _strHeight = this.canvasW +20; //绘制字体距离canvas顶部的初始高度
						let _num = 1;
						for (let i = 0; i < this.title.length; i++) {
							_strlineW += ctx.measureText(this.title[i]).width;
							if (_strlineW > this.canvasW-155) {
								if(_num == 2 && 2){
									//文字换行数量大于二进行省略号处理
									ctx.fillText(this.title.substring(_strLastIndex, i-5)+'...', 40, _strHeight);
									_strlineW = 0;
									_strLastIndex = i;
									_num++;
									break;
								}else{
									ctx.fillText(this.title.substring(_strLastIndex, i), 40, _strHeight);
									_strlineW = 0;
									_strHeight += 20;
									_strLastIndex = i;
									_num++;
								}
							}else if (i == this.title.length - 1) {
								ctx.fillText(this.title.substring(_strLastIndex, i + 1), 40, _strHeight);
								_strlineW = 0;
							}
						}
						/* end */
						
						// ctx.setFontSize(16) // 字号
						// ctx.setFillStyle('#e31d1a') // 颜色
						// ctx.fillText('¥'+this.price, 10, this.canvasW +75); // (文字,x,y)
						// ctx.setFontSize(12)
						// ctx.setFillStyle('#b8b8b8')
						// ctx.fillText('原价¥'+this.Oldprice, 100, this.canvasW +75);
						
						
						// 邀请信息
						ctx.setFontSize(16)
						ctx.setFillStyle('#333')
						ctx.fillText('长按二维码立即预约', this.ewmW + 40, this.canvasW +100);
						
						ctx.setFontSize(16)
						ctx.setFillStyle('#333')
						ctx.fillText('分享自小程序', this.ewmW + 40, this.canvasW +120);
						ctx.draw(false,(ret)=>{ // draw方法 把以上内容画到 canvas 中。
							console.log(ret) 
							uni.showToast({
								icon:'none',
								title: '生成成功!',
							});
							uni.canvasToTempFilePath({ // 保存canvas为图片
								canvasId: 'myCanvas',
								quality: 1,
								fileType:'jpg',
								complete: function(res) {
									// 在H5平台下,tempFilePath 为 base64, // 图片提示跨域 H5保存base64失败,APP端正常输出临时路径
									console.log(res)
									that.canvasShow  = false
									that.shareQrcodeUrl = res.tempFilePath
									that.$forceUpdate()
									setTimeout(function(){
										console.log(that.shareQrcodeUrl,that.canvasShow)
									},2000)
								} ,
							})
						});
					},1500)
				}else{
					console.log('err')
				}
			},
			// 获取图片信息
			getImageInfo(image) {
				return new Promise((req, rej) => {
					uni.getImageInfo({
						src: image,
						success: function(res) {
							req(res)
						},
					});
				})
			},
			
			// 获取设备信息
			getSystemInfo(){
				return new Promise((req, rej) => {
					uni.getSystemInfo({
						success: function (res) {
							req(res)
						}
					});
				})
			},
			//保存图片
			saveShareQrcode(){
				console.log(this.shareQrcodeUrl)
				uni.saveImageToPhotosAlbum({
					filePath: this.shareQrcodeUrl,
					success:(res) => {
						uni.showToast({
							icon: 'none',
							position: 'bottom',
							title: "图片已下载至【图库】,请打开【图库】查看",
						});
					},fail: (err) => {
						//重新提示用户打开保存图片的授权
						if(err.errMsg === "saveImageToPhotosAlbum:fail auth deny"){
							uni.showModal({
								title: '提示',
								content: '需要您授权保存相册',
								showCancel: false,
								success(res) {
									if (res.confirm) {
										uni.openSetting({
											success(settingdata) {
												if (settingdata.authSetting['scope.writePhotosAlbum']) {
													uni.showModal({
														title: '提示',
														content: '获取权限成功,再次保存图片即可成功',
														showCancel: false,
													})
												} else {
													uni.showModal({
														title: '提示',
														content: '获取权限失败,无法保存到相册',
														showCancel: false
													})
												}
											}
										})
									}
								}
							})
						}
					},
				})
			}
		}
	}
</script>

<style lang="scss">
	button{
		height: 88upx;
		background-color: #E85B24;
		color: #fff;
		border-radius: 44upx;
		text-align: center;
		line-height: 88upx;
		width: 60%;
		margin: 0 auto;
		margin-top: 30upx;
	}
</style>

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐