手把手教你用canvas绘制小程序海报(一)在工作中,多多少少都会遇到裂变活动的需求。裂变活动,分享海报也是必不可少的一

背景图+标题+内容+专属头像、昵称+引流二维码是构成海报设计的基本要素。这些基本要素,即是我们需要在代码上实现的功能。可以简单的理解为,要绘制(块、图片)元素、单、多行文字到Canvas中并生成一张海报图片。

分析了要实现的功能,我的脑海浮现出了三种实现的方法:

Talkischeap,Showmethedemo.

小程序的实现,和在web端操作css差别可大了。主要的问题/方法是下面三个:

canvas并没有提供绘制圆角矩形的方法,因此我们需要以另一种方法来实现它。方法的核心是一个叫CanvasContext.arcTo的方法,我们先来看看它的使用的用法:

CanvasRenderingContext2D.arcTo()是Canvas2DAPI根据控制点和半径绘制圆弧路径,使用当前的描点(前一个moveTo或lineTo等函数的止点)。根据当前描点与给定的控制点1连接的直线,和控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,画出两条切线之间的弧线路径。

你可以想象成,一个圆拼命地往一个死角∠挤,挤到极限时,就是我们要的弧线了。控制点1与控制点2连接的直线,作为使用指定半径的圆的切线,所以这条线也是会被无线延长的。千言万语不如一图:

那么,一个矩形的圆角就显得如此的理所当然:

当图片既有背景又有边框又有圆角时,我们就需要以一种取巧的方法来实现:“叠罗汉”。

因为canvas的"图层"遵循先来后来居上原则,后绘制的会盖在先绘制的"图层"上。所以,我们要按顺序的:

CanvasContext.strokeRect能更好得达到绘制边框功能,但它无法设置圆角,所以不使用。

绘制出来的效果如图:

//绘制块元素canvasToDrawBlock(ctx,params){returnnewPromise(async(resolve)=>{const{x,y,url,width,height,radius,border,borderColor,backgroundColor}=paramsif(border){ctx.setFillStyle(borderColor'#fff')this.canvasToDrawArcRectPath(ctx,x-border,y-border,width+border*2,height+border*2,radius )ctx.fill()}if(backgroundColor){ctx.setFillStyle(backgroundColor)this.canvasToDrawArcRectPath(ctx,x,y,width,height,radius)ctx.fill()}if(url){ctx.save()this.canvasToDrawArcRectPath(ctx,x,y,width,height,radius)ctx.clip()const{path:tempImageUrl}=awaitthis.uniGetImageInfoSync(url)ctx.drawImage(tempImageUrl,x,y,width,height)}ctx.restore()resolve()})}绘制单、多行文字通常来说,海报会出现多行的文字。但canvas对文字排版的支持很弱,使我们没办法像使用CSS排版一样愉快的使用canvas进行文字排版。canvas绘制文字时,只会一股脑的在单行上一直画下去而不会根据容器宽度自动换行。

好在canvas中提供了CanvasContext.measureText(stringtext)返回文本宽度的接口。因此,我们只需要把文字逐个计算宽度并绘制,主要步骤如下:

CanvasContext.draw绘制完后,我们再调用uni.canvasToTempFilePath把当前画布指定区域的内容导出海报图片临时地址。需要注意的是,在自定义组件下,需要在第三个参数上绑定当前组件实例的this,以操作组件内canvas组件

既然生成的海报可能几个月都不会更换,那我们完全可以在第一次绘制完海报后,就把文件存入用户本地缓存下次直接使用就好。具体的步骤如下:

constfs=wx.getFileSystemManager()fs.saveFile({tempFilePath:tempCanvasFilePaths,//传入一个本地临时文件路径success:(res)=>{storage.set(this.cacheKey,res.savedFilePath,86400000)this.posterImage=res.savedFilePath}})因此,我们完整的步骤如下:

当然了,你也可以选择把生成海报的途径,转移到web-view上,那你想怎么弄就怎么弄了(滑稽.jpg)。但缺点也很明显:web-view容器会自动铺满整个小程序页面,个人类型的小程序暂不支持使用。

功能暂时就这些了,如果有什么觉得重要的功能需求,可以在issue中提出。后续也可能加入一个可视化操作海报参数的页面。什么时候?下次一定!

THE END
1.unicanvas api介绍 最后有全部代码,复制即用。 data数据 data() { return { myObj: { headImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png', name: '张三', //微信昵称 introduce: '我叫张三今年18岁', introduction: '计算UI设计稿和你手机的屏幕宽度比例(例如UI设计稿是750宽度https://blog.csdn.net/qq_61869009/article/details/135211279
2.更优雅地基于canvas在前端画海报51CTO博客这四个核心方法涵盖了几乎所有海报画图类需求,图片、段落文字、背景容器、画布创建。并且已经把 canvas 相关的 api 收拢了,开发者无需关注恼人的 canvas api,只需要在设计稿上量好尺寸以及位置,就能将对应的元素绝对定位到画布上。 大概业务中的实现(伪代码): https://blog.51cto.com/u_11887782/5891031
3.使用canvas自定义海报(自定义二维码位置实时预览)20px"66:loading="isLoading"67>68提交69</a-button>70</a-form-model-item>71</a-form-model>72</a-col>73<a-col :span="12">74<div>75<div style="margin-bottom:10px">76预览尺寸(px):{{77canvasAttr78? canvasAttr.offsetWidth + " x " +canvasAttr.offsetHeight79: ""80}}(保持纵横比https://www.cnblogs.com/kitty-blog/p/14031798.html
4.小程序自学之路canvas生成弹幕海报基础库 2.7.0 开始支持新版 [Canvas 2D]接口,与 Web一致,但官方文档没有具体的解释。所以我先在菜鸟教程学习基础的知识,用HTML canvas API绘画海报图,然后在微信小程序实现一遍(只需做一下适配,大部分不用变更)。 保存canvas图片失败:canvasToTempFilePath: fail canvas is empty? https://www.jianshu.com/p/22481f0f1639
5.手对手的教你用canvas画一个简单的海报的方法示例html5网页制作企业的广告投入开始从电视等传统媒体向基于圈层文化的新媒体精准营销转移,很多人都想制作一张属于自己的海报,本文介绍了手对手的教你用canvas画一个简单的海报的方法示例,感兴趣的可以了解一下GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用!【 如果你想靠AI翻身,你先需要一个靠谱的工具!】 啦啦啦,首先说下https://www.jb51.net/html5/649963.html