「建议收藏」小程序canvas绘制海报全流程

丰富的线上&线下活动,深入探索云世界

做任务,得社区积分和周边

最真实的开发者用云体验

让每位学生受益于普惠算力

让创作激发创新

资深技术专家手把手带教

遇见技术追梦人

技术交流,直击现场

海量开发者使用工具、手册,免费下载

极速、全面、稳定、安全的开源镜像

开发手册、白皮书、案例集等实战精华

为开发者定制的Chrome浏览器插件

技术选型背景:taro3.0-vue

先来十一个问题压压惊,相信你做绘制海报过程中,一定会遇到

①taro-vuecreateCanvasContext获取canvas实例无效问题,绘制不出来效果?

②taro-vue初始化获取不到canvas上下文怎么办,完全绘制不出来图片?

③关于canvas宽高以及缩放比问题,绘制的元素变形,画布的高度真得等于cavans标签设置的宽高么?

④canvas怎么绘制叠在一起的两张图片,并控制层级?

⑤如何用canvas绘制,多行文本?

⑥如何根据设计稿,精确还原海报各个元素位置问题。

⑦canvas怎么绘制base64的图片

⑧如何绘制网络的图片,两种canvas画布api,绘制图片有什么区别完成

⑨如何正确选型生成二维码工具?

⑩生成的二维码,识别不出来怎么办,

如何绘制二维码上的logo

我们即将解决的问题

②taro-vue初始化获取不到canvas上下文怎么办?

wxml

美好的一天从写一个hello,world开始。

js中这么写

onReady(){/*使用wx.createContext获取绘图上下文context,firstCanvas与canvas属性中的canvas-id一一对应*/constcontext=wx.createCanvasContext('firstCanvas')/*设置字体大小*/context.setFontSize(20)/*设置字体颜色*/context.setFillStyle('pink')/*设置文本内容,位置*/context.fillText('hello,world',0,0)context.draw()}老版本是使用createCanvasContext传入canvas标签中的canvas-id属性,来获取canvas实例,老版本的使用起来说实话,不够灵活,很多对canvas线条,颜色的设置,都封装成方法了,每次改变需要调用方法。

新的方式,则是先通过createSelectorQuery获取canvas元素节点,然后通过getContext获取上下文。

js

constquery=wx.createSelectorQuery()query.select('#myCanvas').fields({node:true,size:true}).exec((res)=>{const{node}=res[0]if(!node)return/*获取canvas实例*/constcontext=node.getContext('2d')context.fillStyle='pink'/*设置字体样式大小字体类别*/context.font='normal40012pxPingFangSC-Regular',context.fillText('hello,world',0,0)})这种方式和第一种createSelectorQuery方式,在api使用方式上会有微妙的差别,这种写法更像原生的DOM写法,设置颜色,样式,直接改变context属性,而不再需要调用对应的api。

解决问题:①taro-vuecreateCanvasContext获取canvas实例无效问题,绘制不出来效果?

因为我们小程序技术选择是taro-vue2,所以我这里重点将一下,在taro-vue中,目前使用createCanvasContext方式获取canvas实例,绘制画布从来没有成功过,即便是createCanvasContext能够创建上下文,但是任何东西也画不出来(传this之类的方案试了一个遍)。要是问我为什么?实际我也不知道,只有凹凸实验室的同学应该更清楚,GitHub上也有issue,希望taro团队能够重视起来。

解决方案就是采用最新的api,就是上述讲的第二个方案。代码如下:

importTarofrom'@tarojs/taro'constquery=Taro.createSelectorQuery()query.select('#myCanvas').fields({node:true,size:true}).exec(res=>{//TODO:....})②taro-vue初始化获取不到canvas上下文怎么办?

在使用taro-vue的过程中,会面临一个问题,就是小程序node节点获取不到的问题,这个有可能是小程序本身的生命周期,和vue生命周期混乱造成的。尤其当我们选择的是组件而不是页面的情况。对于这样的情况,官方文档给出了答案。页面首次渲染完毕时执行,此生命周期在小程序端对应小程序页面的onReady生命周期。从此生命周期开始可以使用createCanvasContext或createselectorquery等API访问真实DOM。

也就是说如果想要获取真是dom节点,我们可以这么做,

组件中

mounted(){eventCenter.once(getCurrentInstance().router.onReady,()=>{constquery=Taro.createSelectorQuery()query.select('#myCanvas').fields({node:true,size:true}).exec(res=>{//TODO:....})})}尴尬的是,这种情况下,有的时候会造成eventCenter.once()回调函数不执行的情况,比如说当前组件的是收到v-if控制的情况。那么怎么样解决呢,对于这种情况,我教大家一种解决方案。

我们可以用taro中,通过Taro.nextTick方法,将获取元素的任务放在下一次nextTick执行。

mounted(){Taro.nextTick(()=>{//获取元素})}2初始化canvas设置宽高百分比我们即将解决的问题: