使用场景
在小程序的一些应用场景中,需要实现在线生成分享海报的功能,方便用户进行多渠道的转发。本篇实践案例就是基于此类场景,讲解如何利用微搭平台实现小程序端生成分享海报的功能。
实现方案
利用编辑器 Canvas 组件生成画布实例、自定义 Js 方法完成绘画、小程序 API
(wx.canvasToTempFilePath)
将画布导出为图片、编辑器弹窗组件展示图片以及小程序 API(wx.saveImageToPhotosAlbum)
实现保存图片。步骤1:准备工作
素材图片:
此次实践准备了两张图片,分别是海报模板和二维码,海报模板用作画布的底图,二维码绘制到画布的右下角(图片可根据需求自行设计),两张图片需要上传到微搭素材库,图片链接可单击图片右下方图标进行复制。


微搭平台授权认证的小程序:
由于生成分享海报功能涉及到小程序 API
(wx.系列方法)
,编辑器下的预览模式无法调用其相关方法,所以在应用发布的时候需要绑定小程序,才能在终端预览真机效果,若之前没有注册过小程序,请在微搭控制台按照指引进行小程序注册、授权认证即可。

步骤2:场景搭建
在编辑器窗口新建按钮组件、弹窗组件以及 Canvas 组件,实现单击下载海报按钮,出现海报弹窗,单击弹窗底部保存到相册按钮,即可保存图片到相册的场景。
说明:
因小程序在编辑器模式(预览模式)和真机模式下,实现场景效果代码方法有所区别,下文将以真机环境下的运行实例进行效果演示,涉及代码片段为生产环境的正式方法。
下载海报按钮:绑定点击事件,执行方法选择组件弹窗。


海报展示弹窗:按下图方式进行配置。
弹窗大纲树结构。


弹窗底部按钮相关设置。


Canvas 组件:放入弹窗容器中,清除初始化代码,宽度设为100%,在渲染完成
canvasReady
事件绑定自定义 JS 方法。

为了更加接近真实场景,在调用上述方法 JS 方法的时候,我们传递三个参数,分别是用户昵称、头像、分享标语(具体传参方式可根据实际场景进行选择)。
说明:
编辑器预览模式下可调用系统方法
$w.auth.currentUser
获取当前用户信息。真机预览模式 PC/H5 请先配置访问控制(PC/H5 端登录配置方法),才可以使用
$w.auth.currentUser
方法获取用户头像、昵称。真机模式小程序请使用小程序 开放接口|用户信息 获取用户微信昵称、头像(若在用户刚打开小程序时就要求收集用户的微信昵称、头像,或者在支付前等不合理路径上要求授权。如果用户拒绝授权,则无法使用小程序或相关功能)。


步骤3:生成海报
Canvas 渲染完成,触发自定义 JS 方法,完成画布绘画并生成图片,自定义 JS 方法核心代码如下:
export default async function ({ event, data }) {/*** canvas相关参数介绍:* $w.组件id.canvasInstance(Weda内置方法): 获取canvas实例* $w.组件id.canvasCtx(Weda内置方法): 获取canvas上下文* clearRect:清除指定的矩形区域,然后这块区域会变得透明* fillRect:绘制一个填充的矩形* fillStyle:填充字体的颜色* fillText:在指定的(x,y)位置填充指定的文本* drawImage:图片基本绘制方法* 更多请参考微搭Canvas组件:https://docs.cloudbase.net/lowcode/components/wedaUI/src/docs/compsdocs/show/WdCanvas* 海报绘制完成之前 ,设置一个loading状态提示 微搭内置交互方法:$w.utils.showLoading*/$w.utils.showLoading({title: "加载中",mask: false,})//获取canvas实例和上下文const canvas = $w.canvas2.canvasInstanceconst ctx = $w.canvas2.canvasCtx//获取可视窗口的宽高const width = $w.device.viewport.widthconst height = $w.device.viewport.height//获取设备像素比let dpr = wx.getWindowInfo().pixelRatioif (ctx && canvas && $w.canvas2?.type === '2d') {// 清空画布ctx.clearRect(0, 0, width, height)//初始化画布大小、画布的最终大小需要按设备像素比进行转换、canvas.width = width * dprcanvas.height = height * dprctx.scale(dpr, dpr)//ctx.fillStyle = "rgb(246, 248, 251,0)";//ctx.fillRect(0, 0, canvas.width, canvas.height)//准备好的poster图片和二维码图片let posterMoudleImg = 'https://lowcode-0ghsfkoo8e3f415d-1258057692.tcloudbaseapp.com/resources/2024-01/lowcode-1579027'let codeImg = 'https://lowcode-0ghsfkoo8e3f415d-1258057692.tcloudbaseapp.com/resources/2024-01/lowcode-1576045'//获取海报图片的尺寸let posterImgInfo = await new Promise((reslove) => {wx.getImageInfo({src: posterMoudleImg,success(res) {reslove(res);}})})// 计算出新的图片宽高(此处以宽为基准,按90%的宽等比例缩放图片)let posterImgRate = posterImgInfo.width / posterImgInfo.heightlet posterWidth = 0.9 * widthlet posterHeight = posterWidth / posterImgRate//获取poster图片信息let posterImg = canvas.createImage()posterImg.src = posterMoudleImgposterImg.onload = async () => {//绘制海报底图let x_position = (width - posterWidth) / 2, y_position = 20ctx.drawImage(posterImg, x_position, y_position, posterWidth, posterHeight)// 绘制用户头像const avatImg = canvas.createImage()avatImg.src = data.target.avataurlavatImg.onload = async () => {//let y4 = y3 + 20ctx.drawImage(avatImg, x_position + 40, posterHeight / 2, 60, 60)}//绘制用户昵称let nickName = "用户ID:" + data.target.nickname;ctx.font = "16px bold";ctx.fillStyle = "white"ctx.fillText(nickName, x_position + 110, posterHeight / 2 + 40);//绘制分享语let shareWords = '"' + data.target.shareWords + '"';ctx.font = "18px bold";ctx.fillStyle = "white"ctx.fillText(shareWords, x_position + 40, posterHeight / 2 + 100);// 绘制小程序码const qrcodeImg = canvas.createImage()qrcodeImg.src = codeImgqrcodeImg.onload = async () => {ctx.drawImage(qrcodeImg, 0.75 * posterWidth, 0.83 * posterHeight, posterWidth / 4, posterWidth / 4)}/*** 把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。暂不支持离屏 canvas。* 更多请参考小程序wx.canvasToTempFilePath方法:https://developers.weixin.qq.com/miniprogram/dev/api/canvas/wx.canvasToTempFilePath.html* success回调参数res.tempFilePath; tempFilePath:图片临时路径* 微搭内置方法:运行终端类型$w.wedaContext.platforms* 微搭内置方法:设置变量tempFilePath并赋值,$w.page.setState({"tempFilePath": res.tempFilePath})*/if ($w.wedaContext.platforms.includes('MP')) {setTimeout(() => {ctx.draw(true, wx.canvasToTempFilePath({x: x_position, // 指定的画布区域的左上角横坐标y: y_position, // 指定的画布区域的左上角纵坐标width: width - x_position * dpr * 2, // 指定的画布区域的宽度height: (width - x_position * dpr * 2) / posterImgRate, // 指定的画布区域的高度destWidth: (width - x_position * dpr * 2) * dpr, // 输出的图片的宽度destHeight: (width - x_position * dpr * 2) / posterImgRate * dpr, // 输出的图片的高度canvas: canvas,//quality: 1,success(res) {$w.page.setState({ "tempFilePath": res.tempFilePath }) //将图片临时路径保存到自定义变量tempFilePath//console.log($w.page.dataset.state.tempFilePath)},fail(res) {console.log('error')$w.utils.showToast({title: "保存失败", // 提示的内容,icon: "error", // 图标,duration: 2000, // 延迟时间,mask: true, // 移动端是否显示透明蒙层(移动端显示透明蒙层可以防止触摸穿透,PC 端不受此配置影响)})},complete(res) {//console.log(res)$w.utils.hideLoading();}}))}, 1500)}}}}
说明:
上述代码为真机模式(生产环境)下的代码,可根据实际需求进行调整,代码片段中涉及重点相关参数、方法、API,如下:
方法 | 作用 | 来源 | 备注 |
$w.组件id.canvasInstance | 获取 Canvas实例 | 微搭内置方法 | |
$w.组件id.canvasCtx | 获取 Canvas 上下文 | 微搭内置方法 | |
$w.device | 获取设备信息 | 微搭内置方法 | |
$w.wedaContext.platforms | 获取终端类型 | 微搭内置方法 | |
wx.getWindowInfo().pixelRatio | 获取设备像素比 | 小程序 API 接口 | |
Canvas.createImage() | 创建图片对象 | 小程序 API 接口 | |
CanvasContext.drawImage() | 绘制图像到画布 | 小程序 API 接口 | |
wx.canvasToTempFilePath() | 将画布导出为图片 | 小程序 API 接口 |
弹窗组件底部按钮绑定点击事件并调用自定义 JS 方法,实现保存图片,自定义 JS 方法核心代码如下:
export default function savePoster() {wx.saveImageToPhotosAlbum({filePath: $w.page.dataset.state.tempFilePath, //图片临时路径success(res) {$w.utils.showToast({title: "保存成功", // 提示的内容,icon: "success", // 图标,duration: 2000, // 延迟时间,mask: true, // 移动端是否显示透明蒙层(移动端显示透明蒙层可以防止触摸穿透,PC 端不受此配置影响)});},fail(res) {$w.utils.showToast({title: "保存失败", // 提示的内容,icon: "error", // 图标,duration: 2000, // 延迟时间,mask: true, // 移动端是否显示透明蒙层(移动端显示透明蒙层可以防止触摸穿透,PC 端不受此配置影响)});}})}
说明:
步骤4:发布应用、真机效果展示
发布应用时请关联已在微搭平台内认证的小程序。


发布成功扫码进入小程序,单击下载海报(小程序真机模式) > 生成海报 > 单击保存到相册 > 保存成功,下面展示的是真机运行效果。




场景应用
小程序分享朋友圈的是“单页模板”的方式,关于相关限制请参见小程序 开放能力 /分享到朋友圈,因此在小程序的实际分享朋友圈的场景中,大多是采用分享海报或者小程序码的形式,由于上述方式中已经讲述了如何生成分享海报的功能,所以只要用实际场景中的小程序码替换掉海报中的二维码,即可复现真实场景的分享功能,小程序码的获取方法:
1. 微信公众平台下载。


2. 应用发布成功之后,在编辑器左侧单击应用设置图标,在应用详情中可以查看应用到小程序码,鼠标右键即可保存图片到本地。


注意事项
注意:
编辑器模式下无法调用小程序相关 API,因此想要在编辑器中预览效果,上述代码需要作出相应调整,涉及到设备分辨率、图片信息、用户信息等获取方式的调整。
可根据实际需求进行相应绘画参数的调整,从而达到理想的海报布局效果。
绘制元素过多的时候,由于
ctx.draw()
是异步方法,请使用 setTimeout()
方法延迟触发,防止导出图片空白问题。若要生成动态二维码,可利用微搭二维码组件,具体请参见 二维码组件使用指引。
其它说明
微信小程序分享朋友圈目前遵循“单页模式”机制:
要求分享的页面里不涉及登录、鉴权、交互等功能,只适合纯内容展示的分享场景。
不允许跳转到其它页面,包括任何跳小程序页面、跳其它小程序、跳微信原生页面。
目前微搭上搭建的小程序涉及到鉴权操作,无法满足微信小程序分享朋友圈的相关要求。
大部分分享朋友圈一般采取的是分享小程序码或者海报的方式,更多请参见 小程序分享朋友圈 相关说明。