微信小程序中使用canvas绘制图片、海报、微信头像和canvas图片的保存

/ 0评 / 1

1. canvas中嵌入图片问题

曾经天真的使用base64自娱自乐许久,最后在真机运行时傻了眼,最后发现只能使用本地临时图片或本地图片来绘制canvas。

本地图片可以直接放置(项目中的图片)

// 本地图片可以直接放置
ctx.drawImage('/packageA/assets/img/poster/poster_bg.png', 0, 0, 350, 500, 0, 0

base64需要转换为本地图片(如后台返回的base64格式图片或二维码等)

function base64ToWxfile(base64,fileName) {
	// 生成的临时路径
	const path = wx.env.USER_DATA_PATH + "/"+ fileName
	return new Promise((reslove, reject) => {
		wx.getFileSystemManager().writeFile({
			filePath: path,
			data: base64,
			encoding: 'base64',
			success: (res) => {
				reslove(path)
			},
			fail: (err) => {
				reject(err)
			}
		})
	})
}
// res为后台返回的base64图片流
const qrCode = res 
// 将base64转为微信临时文件路径
base64ToWxfile(qrCode, "test.png").then(path=>{
	ctx.drawImage(path, 0, 0, 350, 500, 0, 0)
})

线上URL需要转为Base64后存为本地文件

比如当我们从服务器获取的微信头像需要嵌入到canvas时,微信头像的url是一串链接,我们将需要将链接转为base64后再转为本地临时文件。

function urlTobase64(url, ishead = false) {
	return new Promise((reslove, reject) => {
		wx.request({
			url: url,
			responseType: 'arraybuffer', //最关键的参数,设置返回的数据格式为arraybuffer
			success: res => {
				//把arraybuffer转成base64
				let base64 = wx.arrayBufferToBase64(res.data);
				//不加上这串字符,在页面无法显示
				base64 = (ishead ? 'data:image/jpeg;base64,' : '') + base64

				reslove(base64)
			}
		})
	})
}
function base64ToWxfile(base64,fileName) {
	const path = wx.env.USER_DATA_PATH + "/"+ fileName
	return new Promise((reslove, reject) => {
		wx.getFileSystemManager().writeFile({
			filePath: path,
			data: base64,
			encoding: 'base64',
			success: (res) => {
				reslove(path)
			},
			fail: (err) => {
				reject(err)
			}
		})
	})
}
const url = '...'
// 将url转为base64
base64ToWxfile(url).then(base64=>{
	// 将base64转为微信临时文件路径
	base64ToWxfile(base64, "test.png").then(path=>{
		ctx.drawImage(path, 0, 0, 350, 500, 0, 0)
	})
})

2. 关于头像的圆形剪裁

微信返回的头像是方形的,放在海报上着实不好看,所以需要我们自己用canvas做简单的裁剪

// 头像已转为临时文件路径
const avatar = '...'
// 我们需要在头像裁剪前将所有内容放置好
const ctx = wx.createCanvasContext('myCanvas')

// 设置画布背景
ctx.rect(0, 0, 350, 450)
ctx.setFillStyle('#fff')
ctx.fill()
ctx.clip()

// 设置文字
ctx.font = 'normal bold 24px Monospaced Number,Chinese Quote,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif'
// 文字居中(需要配合设置文字所在位置为画布的中间点)	
ctx.textAlign = 'center'
ctx.setFillStyle('#000')
// 所在位置为中间点,可以居中,350/2 = 175
ctx.fillText(user.userName, 175, 180)

ctx.font = 'normal normal 12px Monospaced Number,Chinese Quote,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif'
ctx.fillText('邀请您加入「' + user.companyName + '」', 175, 208)
ctx.setFillStyle('#90959F')
ctx.fillText('长按图片扫码添加', 175, 420)

// 最后做裁剪否则画布只显示裁剪区域
// 开始路径
ctx.beginPath();
// 画出一个圆     y轴、x轴、半径、起始角度、结束角度、顺逆时针
ctx.arc(175, 90, 50, 0, Math.PI * 2, false);
// 结束路径
ctx.closePath()
// 设置圆的背景色为白色
ctx.setFillStyle('#fff')
ctx.fill()
ctx.clip()
// 放置图片
ctx.drawImage(avatarUrl, 125, 40, 100, 100, 0, 0)
ctx.draw()
ctx.beginPath()
ctx.draw(true);

3. 关于小程序中canvas转为图片保存到手机相册

// canvas转为本地临时文件
wx.canvasToTempFilePath({
	x: 0,
	y: 0,
	width: 350,
	height: 450,
	canvasId: 'myCanvas',
	success: function(res) {
		let img = res.tempFilePath
		// 保存至本地,此时会弹窗要求用户授权
		wx.saveImageToPhotosAlbum({
			filePath: img,
			success(json) {
				app.toast('成功保存', 'success')
			},
			fail(err) {
				app.toast('保存失败', err)
			}
		})
	},
	fail(err) {
		console.log(err)
	}
})

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注