一、实现方案
利用编辑器 Canvas 组件生成画布实例、自定义 JS 方法完成绘画、小程序 API(wx.canvasToTempFilePath)将画布导出为图片、编辑器弹窗组件展示图片以及小程序 API(wx.saveImageToPhotosAlbum)实现保存图片。
二、步骤1:准备工作
·素材图片:
此次实践准备了两张图片,分别是海报模板和二维码,海报模板用作画布的底图,二维码绘制到画布的右下角(图片可根据需求自行设计),两张图片需要上传到微搭素材库,图片链接可单击图片右下方图标进行复制。
·微搭平台授权认证的小程序:
由于生成分享海报功能涉及到小程序 API(wx.系列方法),编辑器下的预览模式无法调用其相关方法,所以在应用发布的时候需要绑定小程序,才能在终端预览真机效果,若之前没有注册过小程序,请在微搭控制台按照指引进行小程序注册、授权认证即可。
三、步骤2:场景搭建
在编辑器窗口新建按钮组件、弹窗组件以及 Canvas 组件,实现单击下载海报按钮,出现海报弹窗,单击弹窗底部保存到相册按钮,即可保存图片到相册的场景。
注意:说明:
注意:因小程序在编辑器模式(预览模式)和真机模式下,实现场景效果代码方法有所区别,下文将以真机环境下的运行实例进行效果演示,涉及代码片段为生产环境的正式方法。
·下载海报按钮:绑定点击事件,执行方法选择组件弹窗。
·海报展示弹窗:按下图方式进行配置。
·弹窗大纲树结构。
·弹窗底部按钮相关设置。
·Canvas 组件:放入弹窗容器中,清除初始化代码,宽度设为100%,在渲染完成 canvasReady 事件绑定自定义 JS 方法 downLoadPoster。
·为了更加接近真实场景,在调用上述方法 JS 方法的时候,我们传递三个参数,分别是用户昵称、头像、分享标语(具体传参方式可根据实际场景进行选择)。
注意:说明:
四、步骤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.canvasInstance const ctx = $w.canvas2.canvasCtx //获取可视窗口的宽高 const width = $w.device.viewport.width const height = $w.device.viewport.height //获取设备像素比 let dpr = wx.getWindowInfo().pixelRatio if (ctx && canvas && $w.canvas2?.type === '2d') { // 清空画布 ctx.clearRect(0, 0, width, height) //初始化画布大小、画布的最终大小需要按设备像素比进行转换、 canvas.width = width * dpr canvas.height = height * dpr ctx.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.height let posterWidth = 0.9 * width let posterHeight = posterWidth / posterImgRate //获取poster图片信息 let posterImg = canvas.createImage() posterImg.src = posterMoudleImg posterImg.onload = async () => { //绘制海报底图 let x_position = (width – posterWidth) / 2, y_position = 20 ctx.drawImage(posterImg, x_position, y_position, posterWidth, posterHeight) // 绘制用户头像 const avatImg = canvas.createImage() avatImg.src = data.target.avataurl avatImg.onload = async () => { //let y4 = y3 + 20 ctx.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 = codeImg qrcodeImg.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 端不受此配置影响) }); } })}
注意:说明:
注意:小程序 APIwx.saveImageToPhotosAlbum() 保存图片到系统相册,具体请参见 小程序产品文档。
五、步骤4:发布应用、真机效果展示
·发布应用时请关联已在微搭平台内认证的小程序。
·发布成功扫码进入小程序,单击下载海报(小程序真机模式) > 生成海报 > 单击保存到相册 > 保存成功,下面展示的是真机运行效果。
六、场景应用
小程序分享朋友圈的是“单页模板”的方式,关于相关限制请参见小程序 开放能力 /分享到朋友圈,因此在小程序的实际分享朋友圈的场景中,大多是采用分享海报或者小程序码的形式,由于上述方式中已经讲述了如何生成分享海报的功能,所以只要用实际场景中的小程序码替换掉海报中的二维码,即可复现真实场景的分享功能,小程序码的获取方法:
1. 微信公众平台下载。
2. 应用发布成功之后,在编辑器左侧单击应用设置图标,在应用详情中可以查看应用到小程序码,鼠标右键即可保存图片到本地。
七、其它说明
微信小程序分享朋友圈目前遵循“单页模式”机制:
·要求分享的页面里不涉及登录、鉴权、交互等功能,只适合纯内容展示的分享场景。
·不允许跳转到其它页面,包括任何跳小程序页面、跳其它小程序、跳微信原生页面。
·目前微搭上搭建的小程序涉及到鉴权操作,无法满足微信小程序分享朋友圈的相关要求。
·大部分分享朋友圈一般采取的是分享小程序码或者海报的方式,更多请参见 小程序分享朋友圈 相关说明。