- u-draw-poster canvas 海报绘制工具
绘制海报工具简述 创建绘制海报[代码]canvas[代码]矩形方法,内置了图片绘制,圆角矩形绘制,换行字体绘制等方法。 接近原生开发体验,上手快,只需考虑业务逻辑,而不用考虑其他问题。 拥有良好的语法架构,不会在绘制[代码]uni/wx[代码]矩形时陷入回调地狱。 支持原生小程序,与[代码]uniapp[代码]多端应用。当是环境为原生小程序时,自动切换为性能更好的[代码]type2d[代码]绘制方式。 将复杂的逻辑组合为简单的方法,扩展性强,可使用 [代码]use|useCtx[代码] 引入扩展。 支持[代码]typescript[代码],支持[代码]vue3[代码]模板,具体使用参考 useDrawPoster。 更加强大的图片绘制与裁剪方法(object-fit) api文档:u-draw-poster 插件市场:dcloud/u-draw-poster npm 安装插件 [代码]npm i --save-dev u-draw-poster [代码] 1. 创建海报绘制工具 [代码]<!-- #ifdef MP-WEIXIN --> <canvas id="canvas" type="2d" style="width:100px; height:100px" /> <!-- #endif --> <!-- #ifndef MP-WEIXIN --> <canvas canvas-id="canvas" id="canvas" style="width:100px; height:100px" /> <!-- #endif --> [代码] [代码]// 注意:如果使用HBuilder引入, 需要引入 '@/js_sdk/u-draw-poster' import DrawPoster from 'u-draw-poster' async onReady() { // 传入选择器, 初始化绘制工具(注意, 不需要传入#符号) 当微信小程序时, 将自动启用type2d绘制 const dp = await DrawPoster.build("canvas") } [代码] 2. 设置画布尺寸 [代码]// 设置长高为100px的矩形宽高 dp.canvas.width = 100 dp.canvas.height = 100 [代码] 3. 绘制任意内容 [代码]// 绘制背景与文字 dp.draw((ctx) => { ctx.fillStyle = "#F4F4F4"; ctx.fillRect(0, 0, dp.canvas.width, dp.canvas.height); ctx.textBaseline = "top"; ctx.textAlign = "start"; ctx.fillStyle = "white"; ctx.font = `bold ${22}px sans-serif`; ctx.fillText('周先生', dp.canvas.width/2, 38.5); }) // 绘制图片内容 dp.draw(async (ctx) => { //....... }) [代码] 值得注意的是, [代码]draw[代码]方法会自动的执行[代码]ctx.save/ctx.restore[代码], 不需要人为操纵绘画栈. [代码]dp.draw((ctx) => {/* ... */}) // 相当于 ctx.save() /* ... */ ctx.restore() [代码] 4. 进行绘制 [代码]dp.draw[代码]并不会马上绘制,只是将该任务添加到了任务栈,需要使用[代码]dp.awaitCreate[代码]函数进行绘制,该函数在绘制完毕后将弹出所有任务。 [代码]dp.awaitCreate[代码]在非[代码]2d[代码]绘画中,执行绘画任务完毕后,将自动执行[代码]ctx.draw[代码]方法,并在draw绘画才算异步结束。 [代码]dp.draw((ctx) => {/* ... */}) dp.draw(async (ctx) => {/* ... */}) // 由于每个任务都有可能会有异步的绘制任务, 所以得需要使用await等待绘制 const result = await dp.awaitCreate(); // 绘制成功将返回每个任务的绘制状况组成的数组 console.log("draw绘制状况:", result); // draw绘制状况: [true] [代码] 5. 生成图片本地地址 如需要保存为图片时,可以使用[代码]dp.createImgUrl[代码] 进行创建图片本地地址,在由[代码]wx[代码]或[代码]uni[代码]的[代码]api[代码]进行保存。 [代码]dp.draw(async (ctx) => {/* ... */}) const result = await dp.awaitCreate(); const posterImgUrl = await dp.createImagePath(); console.log("draw绘制状况:", result); // [true] console.log("绘制生成本地地址:", posterImgUrl); // ...tmp... [代码] 你也可以不使用[代码]dp.awaitCreate[代码]方法,当调用[代码]dp.createImagePath[代码]时会自动检测任务列表,如果有则执行绘制任务后在创建地址。 [代码]dp.draw(async (ctx) => {/* ... */}) // 跳过drawPoster.awaitCreate直接生成地址 const posterImgUrl = await dp.createImagePath(); console.log("绘制生成本地地址:", posterImgUrl); [代码] 绘制扩展 API DrawPoster 在创建时,会自动的向[代码]ctx(画笔)[代码]添加/覆盖扩展方法,以便构建海报矩形。 目前支持绘制图片、圆角图片、绘制裁剪图片(object-fit)、换行字体、圆角矩形、圆角矩形边框、绘制二维码。 [代码]dp.draw(async (ctx) => { // ctx.drawImage | ctx.drawRoundImage | ctx.fillWarpText | .... }) [代码] 具体查看API文档:u-draw-poster 全局实例 API DrawPoster 的静态与扩展方法,除了最常用的:绘制节点、绘画构建、创建绘制、创建图片,以及还有另外的扩展功能:绘画构建、挂载全局扩展、挂载绘制扩展、全局画笔、等待绘制、停止绘画。 具体查看API文档:u-draw-poster
2021-01-02 - 如何实现快速生成朋友圈海报分享图
由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种(坑)彩dan了吧~ 这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能) 咱们不多说,直接上手就是干。 [图片] 首先我们新增一个自定义组件,在该组件的json中引入painter [代码]{ "component": true, "usingComponents": { "painter": "/painter/painter" } } [代码] 然后组件的WXML (代码片段在最后) [代码]// 将该组件定位在屏幕之外,用户查看不到。 <painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" /> [代码] 重点来了 JS (代码片段在最后) [代码]Component({ properties: { // 是否开始绘图 isCanDraw: { type: Boolean, value: false, observer(newVal) { newVal && this.handleStartDrawImg() } }, // 用户头像昵称信息 userInfo: { type: Object, value: { avatarUrl: '', nickName: '' } } }, data: { imgDraw: {}, // 绘制图片的大对象 sharePath: '' // 生成的分享图 }, methods: { handleStartDrawImg() { wx.showLoading({ title: '生成中' }) this.setData({ imgDraw: { width: '750rpx', height: '1334rpx', background: 'https://qiniu-image.qtshe.com/20190506share-bg.png', views: [ { type: 'image', url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg', css: { top: '32rpx', left: '30rpx', right: '32rpx', width: '688rpx', height: '420rpx', borderRadius: '16rpx' }, }, { type: 'image', url: this.data.userInfo.avatarUrl || 'https://qiniu-image.qtshe.com/default-avatar20170707.png', css: { top: '404rpx', left: '328rpx', width: '96rpx', height: '96rpx', borderWidth: '6rpx', borderColor: '#FFF', borderRadius: '96rpx' } }, { type: 'text', text: this.data.userInfo.nickName || '青团子', css: { top: '532rpx', fontSize: '28rpx', left: '375rpx', align: 'center', color: '#3c3c3c' } }, { type: 'text', text: `邀请您参与助力活动`, css: { top: '576rpx', left: '375rpx', align: 'center', fontSize: '28rpx', color: '#3c3c3c' } }, { type: 'text', text: `宇宙最萌蓝牙耳机测评员`, css: { top: '644rpx', left: '375rpx', maxLines: 1, align: 'center', fontWeight: 'bold', fontSize: '44rpx', color: '#3c3c3c' } }, { type: 'image', url: 'https://qiniu-image.qtshe.com/20190605index.jpg', css: { top: '834rpx', left: '470rpx', width: '200rpx', height: '200rpx' } } ] } }) }, onImgErr(e) { wx.hideLoading() wx.showToast({ title: '生成分享图失败,请刷新页面重试' }) //通知外部绘制完成,重置isCanDraw为false this.triggerEvent('initData') }, onImgOK(e) { wx.hideLoading() // 展示分享图 wx.showShareImageMenu({ path: e.detail.path, fail: err => { console.log(err) } }) //通知外部绘制完成,重置isCanDraw为false this.triggerEvent('initData') } } }) [代码] 那么我们该如何引用呢? 首先json里引用我们封装好的组件share-box [代码]{ "usingComponents": { "share-box": "/components/shareBox/index" } } [代码] 以下示例为获取用户头像昵称后再生成图。 [代码]<button class="intro" bindtap="getUserInfo">点我生成分享图</button> <share-box isCanDraw="{{isCanDraw}}" userInfo="{{userInfo}}" bind:initData="handleClose" /> [代码] 调用的地方: [代码]const app = getApp() Page({ data: { isCanDraw: false }, // 组件内部关掉或者绘制完成需重置状态 handleClose() { this.setData({ isCanDraw: !this.data.isCanDraw }) }, getUserInfo(e) { wx.getUserProfile({ desc: "获取您的头像昵称信息", success: res => { const { userInfo = {} } = res this.setData({ userInfo, isCanDraw: true // 开始绘制海报图 }) }, fail: err => { console.log(err) } }) } }) [代码] 最后绘制分享图的自定义组件就完成啦~效果图如下: [图片] tips: 文字居中实现可以看下代码片段 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号 代码片段:https://developers.weixin.qq.com/s/J38pKsmK7Qw5 附上painter可视化编辑代码工具:点我直达,因为涉及网络图片,代码片段设置不了downloadFile合法域名,建议真机开启调试模式,开发者工具 详情里开启不校验合法域名进行代码片段的运行查看。 最后看下面大家评论问的较多的问题:downLoadFile合法域名在小程序后台 开发>开发设置里配置,域名为你图片的域名前缀 比如我文章里的图https://qiniu-image.qtshe.com/20190605index.jpg。配置域名时填写https://qiniu-image.qtshe.com即可。如果你图片cdn地址为https://aaa.com/xxx.png, 那你就配置https://aaa.com即可。
2022-01-20 - weapp-qrcode-canvas-2d在微信小程序中生成二维码,新版canvas-2d接口
weapp-qrcode-canvas-2d weapp-qrcode-canvas-2d 是使用新版canvas-2d接口在微信小程序中生成二维码(外部二维码)的js包。canvas 2d 接口支持同层渲染且性能更佳,建议切换使用,可大幅提升生成图片的速度。 仓库地址 weapp-qrcode-canvas-2d【码云gitee】 weapp-qrcode-canvas-2d【github】 [图片] 测试环境 微信小程序基础库版本:2.10.4 开发者工具版本:Stable 1.03.2101150 Usage 先在 wxml 文件中,创建绘制的 [代码]canvas[代码],并定义好 [代码]width[代码], [代码]height[代码], [代码]id[代码] , [代码]type[代码] ,其中type的值必须为[代码]2d[代码] [代码]<canvas type="2d" style="width: 260px; height: 260px;" id="myQrcode"></canvas> [代码] 安装方法1:直接引入 js 文件 直接引入 js 文件,使用 [代码]drawQrcode()[代码] 绘制二维码 [代码]// 将 dist 目录下,weapp.qrcode.esm.js 复制到项目中。路径根据实际引用的页面路径自行改变 import drawQrcode from '../../utils/weapp.qrcode.esm.js' [代码] 安装方法2:npm安装 [代码]npm install weapp-qrcode-canvas-2d --save [代码] // 然后需要在小程序开发者工具中:构建npm [代码]import drawQrcode from 'weapp-qrcode-canvas-2d' [代码] 安装完成后调用 例子1:没有使用叠加图片 [代码]const query = wx.createSelectorQuery() query.select('#myQrcode') .fields({ node: true, size: true }) .exec((res) => { var canvas = res[0].node // 调用方法drawQrcode生成二维码 drawQrcode({ canvas: canvas, canvasId: 'myQrcode', width: 260, padding: 30, background: '#ffffff', foreground: '#000000', text: 'abc', }) // 获取临时路径(得到之后,想干嘛就干嘛了) wx.canvasToTempFilePath({ canvasId: 'myQrcode', canvas: canvas, x: 0, y: 0, width: 260, height: 260, destWidth: 260, destHeight: 260, success(res) { console.log('二维码临时路径:', res.tempFilePath) }, fail(res) { console.error(res) } }) }) [代码] 例子2:使用叠加图片(在二维码中加logo) [代码]const query = wx.createSelectorQuery() query.select('#myQrcode') .fields({ node: true, size: true }) .exec((res) => { var canvas = res[0].node var img = canvas.createImage(); img.src = "/image/logo.png" img.onload = function () { // img.onload完成后才能调用 drawQrcode方法 var options = { canvas: canvas, canvasId: 'myQrcode', width: 260, padding: 30, paddingColor: '#fff', background: '#fff', foreground: '#000000', text: '123456789', image: { imageResource: img, width: 80, // 建议不要设置过大,以免影响扫码 height: 80, // 建议不要设置过大,以免影响扫码 round: true // Logo图片是否为圆形 } } drawQrcode(options) // 获取临时路径(得到之后,想干嘛就干嘛了) wx.canvasToTempFilePath({ x: 0, y: 0, width: 260, height: 260, destWidth: 600, destHeight: 600, canvasId: 'myQrcode', canvas: canvas, success(res) { console.log('二维码临时路径为:', res.tempFilePath) }, fail(res) { console.error(res) } }) }; }) [代码] API drawQrcode([options]) options Type: Object 参数 必须 说明 示例 canvas 必须 画布标识,传入 canvas 组件实例 canvasId 非 绘制的[代码]canvasId[代码] [代码]'myQrcode'[代码] text 必须 二维码内容 ‘123456789’ width 非 二维码宽度,与[代码]canvas[代码]的[代码]width[代码]保持一致 260 padding 非 空白内边距 20 paddingColor 非 内边距颜色 默认与background一致 background 非 二维码背景颜色,默认值白色 [代码]'#ffffff'[代码] foreground 非 二维码前景色,默认值黑色 [代码]'#000000'[代码] typeNumber 非 二维码的计算模式,默认值-1 8 correctLevel 非 二维码纠错级别,默认值为高级,取值:[代码]{ L: 1, M: 0, Q: 3, H: 2 }[代码] 1 image 非 在 canvas 上绘制图片,层级高于二维码,v1.1.1+版本支持。具体使用见:例子2 [代码]{imageResource: '', width:80, height: 80, round: true}[代码]
2023-04-02