微信小程序使用canvas画海报分享图

项目场景:

很多小程序都会有一些分享海报的需求。因为我这边之前一直都是后端直接生成一张图片然后返回了的,我前端直接把路径放上去就可以了。但是,有时候后端没直接生成海报,而是只生成了一个二维码,这时候就需要我们前端来合成海报。虽然也可以直接叫后端做,但是身为前端人员,不能什么事都让后端来实现,前端也能实现。这时候就需要用到canvas来把数据都画进去了。

实现步骤:

1.先需要在代码里定义一个canvas标签(我这里用的是一个vant的弹窗,可以换别的)

注意这里的canvas最好使用v-show来显示或隐藏,否则用v-if的话会把画布销毁掉。

<van-popup :show="showShareImg" @close="onCloseShare()" :closeable="true" :close-on-click-overlay="true"
	position="bottom">
	<view style="overflow: hidden;">
		<canvas v-show="showShareImg" style="width: 100%; height: 800rpx;overflow: hidden;"
			canvas-id='myCanvas'></canvas>
		<view style="font-size: 12px;color: #757575;text-align: center;">图片保存到相册后,随时可分享到你的圈子</view>
		<view style="width: 70%;margin: 35rpx auto;">
			<button @click="saveCanvasImg" type="primary" size="default"
				style="height: 75rpx;line-height: 75rpx;font-size: 16px;border-radius: 40rpx;background-color: #3e84f9 ;">保存图片</button>
		</view>
	</view>
</van-popup>

//data数据
data(){
	return{
		showShareImg: false, //悬浮按钮点击的弹出层
		screenWidth: "", //屏幕宽度
		myCanvas: ""
	}
}

在这里插入图片描述

2. 实现方法

async onLoad() {
	//这里需要获取到手机屏幕的宽度,下面有用到,不然没办法让那些文字居中显示
	let systemInfo = await wx.getSystemInfo() //获取屏幕宽度
	this.screenWidth = systemInfo.screenWidth
},
method:{
	//点击分享 我这里的type只是下面后端的接口有需要传的参数而已。如果没有参数,可以不传
	clickShowShare() {
		this.saveCanvas('room')
	},
	//关闭分享
	onCloseShare() {
		this.showShareImg = false
	},
	//canvas画图保存到相册
	 saveCanvas(type) {
		wx.showLoading({
			title:"加载中"
		})
		if (this.myCanvas != "") {
			this.myCanvas.restore() //恢复canvas之前保存的状态
			wx.hideLoading()
			this.showShareImg = true
			return
		}
		const ctx = wx.createCanvasContext('myCanvas') //创建画布
		this.myCanvas = ctx
		ctx.setFillStyle('#ffffff') //设置填充色
		ctx.fillRect(40, 2, this.screenWidth - 80, 360); //设置背景颜色的 -- 绘制"被填充"的矩形。
		ctx.save() //保存当前的绘图上下文。
		ctx.beginPath() //开始创建一个路径 -- 好像不用也行
		ctx.setFillStyle('#626262') //文字颜色
		ctx.setFontSize(16) //文字大小
		ctx.setTextAlign('left') //文字水平方向,基于下面的宽
		let str = '推荐预约会议室'
		//fillText(文本,距离左边多长,距离顶部多高)
		ctx.fillText(str, (this.screenWidth - ctx.measureText(str).width) / 2, 30) //measureText 计算文本宽度 (屏幕宽度-文字宽度)/2  大概就是这些位置居中
		
		wx.downloadFile({
			//直接把路径带上 网络路径
			url: "https://xxxxxxxxx/appointment/getShareServiceQrcode?type="+type,
			success: (res) => {
				//drawImage图片画入 ,drawImage(微信的临时路径,距离左边宽度,距离顶部高度)
				ctx.drawImage(res.tempFilePath, (this.screenWidth - 200) / 2, 50, 200, 200)
				ctx.draw(true) //参数为 true,则保留当前画布上的内容,否则画布前面的内容会被清空
				wx.hideLoading()
				this.showShareImg = true
			},
			fail:(res)=>{
				wx.showToast({
					title:"加载失败"
				})
				wx.hideLoading()
			}
		})
		ctx.setFontSize(13) //文字大小
		ctx.setFillStyle("#757575") //文字颜色
		let str2 = '长按识别小程序码,即刻预约会议室'
		ctx.fillText(str2, (this.screenWidth - ctx.measureText(str2).width) / 2, 280)
		ctx.setFillStyle("#333333")
		ctx.setFontSize(15) //文字大小
		let str3 = '南沙国际人才港共享会议室,满足各种开会'
		let str4 = '场景需求,为企业及人才提供一站式服务'
		ctx.fillText(str3, (this.screenWidth - ctx.measureText(str3).width) / 2, 320) //同上
		ctx.fillText(str4, (this.screenWidth - ctx.measureText(str4).width) / 2, 340)
		/* 裁剪 */
		//总长度-左边40+右边40 == this.screenWidth-80
		ctx.rect(40, 2, this.screenWidth - 80, 360) //画一个矩形裁剪区域
		ctx.clip() //裁剪
		ctx.save() //保存当前的绘图上下文。
	},
	//保存canvas图片到相册
	saveCanvasImg() {
		wx.canvasToTempFilePath({ //把当前画布指定区域的内容导出生成指定大小的图片
			canvasId: 'myCanvas',
			success(res) {
				wx.authorize({ //向用户发起授权请求
					scope: 'scope.writePhotosAlbum', //保存相册授权
					success: () => {
						wx.saveImageToPhotosAlbum({ //保存图片到系统相册
							filePath: res.tempFilePath,
							success: () => {
								wx.showToast({
									title: '图片保存成功'
								})
							}
						})
					}
				})
			}
		})
	},
}

最后效果图:

1.页面图

在这里插入图片描述

2. 导出分享图

在这里插入图片描述

最终:

收工!!!第一版,可能还有很多可以优化,希望有用到的小伙伴,有什么新想法可以评论区讨论,共同进步噢!


版权声明:本文为weixin_45923100原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。