最近给自己的拼团小程序添加一个海报分享的功能,由于要分享特定的商品,需要动态路由的二维码,这样的话,就没办法直接内置一个二维码了,只能向后端请求,然后保存到本地。但是不想动后端的接口了,就想到了只用前端生成:
下面是实现流程思路:
1.向后端请求指定商品id路由的参数,后端返回该页面的二维码海报:放弃!
2.使用云函数获取小程序二维码,支持路由参数,保存到小程序本地,通过canvas绘制,生成海报:Bingo!
然后就是编码的问题:
1.云函数的使用
2.canvas绘制网络图片(需要先使用wx.getImageInfo拿到临时路径)
3.动态设置海报的尺寸
4.定制其它内容(头像,文本)
效果图:
在这个过程中:点击分享按钮,把canvas的hidden关闭(canvas层级太高),开始绘制封面图(网络路径),请求小程序码,绘制小程序码,绘制文本,由于有时候延迟很大,所以去除了头像绘制,代码会给出示例。
开始代码
//绘制海报
renderShare() {
let that = this;
//绘制背景
ctx.save();
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, this.data.windowWidth * .8, this.data.windowWidth * .8 + 120);
ctx.draw()
ctx.restore();
ctx.setFontSize(18)
ctx.fillStyle = "#000000";
ctx.fillText(`一起来扫码领【${this.data.goods_info.coupon_discount / 100}元券】`, 90, this.data.windowWidth * .8 + 75)
ctx.draw(true)
ctx.save()
//console.log(e);
// let avatarurl_width = 60,
// avatarurl_heigth = 60,
// avatarurl_x = 30, //绘制的头像在画布上的位置
// avatarurl_y = 30; //绘制的头像在画布上的位置
// ctx.beginPath();
//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针
//ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
// ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸
console.log('开始绘制')
// ctx.drawImage(e.path, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片
wx.getImageInfo({
src: that.data.goods_info.goods_gallery_urls[0],
success(ee) {
console.log(ee)
ctx.restore()
//计算海报宽度
let paperW = that.data.windowWidth * .8;
//计算图片居中
ctx.drawImage(ee.path, 0, 0, paperW, paperW)
ctx.draw(true)
console.log(ctx);
//获取小程序码
const res = wx.cloud.callFunction({
// 要调用的云函数名称
name: 'getCodeImg',
data: {
goods_id: that.data.goods_info.goods_id
}
});
res.then((code) => {
console.log(code)
console.log(code_filePath)
fsm.writeFile({
filePath: code_filePath,
data: code.result.buffer,
encoding: 'binary',
success() {
console.log(code_filePath)
console.log(code_filePath)
wx.getImageInfo({
src: code_filePath,
success(code_result) {
console.log(code_result)
ctx.drawImage(code_result.path, 30, that.data.windowWidth * .8 + 40, 52.2, 59.4)
ctx.draw(true)
//canvas生成图片
wx.canvasToTempFilePath({
canvasId: 'shareImg',
success(canvas_img) {
canvas_imgPath = canvas_img.tempFilePath;
},
fail(canvas_fail) {
console.log(canvas_fail)
},
complete(e){
wx.hideToast(tips)
}
}, this)
}
})
},
fail() {
},
});
});
}
})
},
这里注意几个地方:canvas绘制网络图一定要先用wx的API转换成临时文件再绘制。
没有使用过云函数的小伙伴看这里:微信官方为我们提供了云函数的便利,我们需要在本地建立一个云函数的目录,开发工具会自动识别,比如我这里建立了cloudfunctions后面的| shell-goods是工具自动添加的!
在里面我们可以建立云函数目录,比如这个getCodeImg
一个函数是一个目录哦,打开只有config.js和index.js 下面就是index.js的内容,具体请移步微信文档:云开发
一个小提示:关于引入
const cloud = require('wx-server-sdk')
需要使用NPM安装哦
然后最后一步就是不要忘记,右键云函目录,点击部署!!!
之后在其它页面我们就可以使用下面的方式调用了,参数也是可以传的。
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
// 获取小程序码
exports.main = async(event, context) => {
let result = await cloud.openapi.wxacode.createQRCode({
path: 'pages/shop/goods/goods?goods_id=' + event.goods_id,
//是否透明底图
is_hyaline: true,
width: 300
});
console.log(result)
return result
}
其实如果可以,还是尽量从后端生成比较好,快速,尤其是想绘制背景的时候,前端本地每次都要将网络转为临时文件再绘制到canvas太慢了。
onLoad拿到入口参数
if (lauchInfo.query.goods_id != undefined && lauchInfo.query.goods_id.goods_id != ""){
mThis.initData(lauchInfo.query.goods_id);
console.log("sc")
return false
}