小程序中利用canvas进行海报绘制的方式

在canvas上绘制图片/文字的时候,我们设定canvas:375*667的宽高,会发现绘制出来的图片很模糊,感觉像是一张分辨率很差的图片,文字看起来也会有叠影。

原因:在前端开发中我们知道一个属性叫devicePixelRatio(设备像素比),该属性决定了在渲染界面时会用几个(通常是2个)物理像素来渲染一个设备独立像素。

举个例,一张100*100像素大小的图片,在retina屏幕下,会用2个像素点去渲染图片的一个像素点,相当于图片放大了一倍,因此图片会变得模糊,这也是1px在retina屏上变粗的原因。

解决:将canvas-width和canvas-height都放大2倍,在通过style将canvas的显示width,height缩小2倍.

例如:

1

在绘制海报的之前,我们拿到的设计稿一般都是基于iphone6的2倍图。而且从上一个问题的解决,我们知道canvas的大小也是2倍的,所以我们可以直接量取2倍图的设计稿直接绘制canvas,而尺寸需要注意一下rpxtoPx.

2

3

4

5

6

7

8

9

10

11

12

13

/**

*

*@param{*}rpx

*@param{*}int//是否变成整数

factor=>0.5//iphone6

pixelRatio=>2像素比

*/

toPx(rpx,int){

if(int){

returnparseInt(rpx*this.factor*this.pixelRatio)

}

returnrpx*this.factor*this.pixelRatio

14

15

16

17

18

19

20

21

22

23

24

25

26

27

measureText(text,fontSize=10){

text=String(text)

letwidth=0

text.forEach(function(item){

if(/[a-zA-Z]/.test(item)){

width+=7

}elseif(/[0-9]/.test(item)){

width+=5.5

}elseif(/\./.test(item)){

width+=2.7

}elseif(/-/.test(item)){

width+=3.25

}elseif(/[\u4e00-\u9fa5]/.test(item)){//中文匹配

width+=10

}elseif(/\(|\)/.test(item)){

width+=3.73

}elseif(/\s/.test(item)){

width+=2.5

}elseif(/%/.test(item)){

width+=8

}else{

})

returnwidth*fontSize/10

字体的如果过长,会超出canvas画布,造成绘制难看,这个时候我们就应该让超出的部分变成...你可以设置一个width并且循环计算计算出文本的宽度,如果超出则利用substring截取后补充...即可。

letwidth=350

for(leti=0;i=width){

if(line===lineNum){

if(i!==text.length-1){

if(line

文字剧中展示计算公式:

居中在canvas中可以用(canvas的宽度-文字宽度)/2+x(x为字体的x轴的推移)

letw=this.measureText(text,this.toPx(fontSize,true))

this.ctx.fillText(text,this.toPx((this.canvas.width-w)/2+x),this.toPx(y+(lineHeight||fontSize)*index))

先把base64转成Uint8ClampedArray格式。然后再通过wx.canvasPutImageData(OBJECT,this)绘制到画布上,然后把画布导出为图片。

使用Canvas绘图成功后,直接调用该方法生成图片,在IDE上没有问题,但在真机上会出现生成的图片不完整的情况,可以使用一个setTimeout来解决这个问题。

this.ctx.draw(false,()=>{

setTimeout(()=>{

Taro.canvasToTempFilePath({

success:async(res)=>{

this.props.onSavePoster(res.tempFilePath)//回调事件

//清空画布

this.ctx.clearRect(0,0,canvas_width,canvas_height)

},

fail:(err)=>{

console.log(err)

},this.$scope)

},time)

fontsize不能使用小数如果设置font中字体大小部分包含小数,则会导致整个font设置无效。

这个问题出现在安卓手机上,ios表现正常。一开始看到这个问题,摸不着头脑,为什么有的正常居中有的却往前了很多。后面发现是安卓下this.ctx.setTextAlign(textAlign)默认是为center,所以导致了错乱,改成left后就正常了。

利用canvas绘制一个简单的折线图,只需要利用lineTo和moveTo俩个API将点连接即可。利用createLinearGradient绘制阴影。

现在的海报生成只需要按照设计稿去量取尺寸就可以,但是量取的过程还是很繁琐的,在设计稿量不到的地方还需要手动微调一下。后续还可以做一个web端使用拖拽的方式去完成设计稿的事情,自动生成json应用到小程序的海报上。

前端生成海报的时候我发现耗时更长,包括图片的-本地而且还需要给安卓一个特意写一个setTimeout去确保绘制正常。各种兼容性问题、手机的dpr、安卓和ios等不间断彩蛋踩到你头秃~哈哈哈哈~

在canvas开发的过程中,小程序里一直有一束微光提醒我。

我也试了试最新的canvas2d的api,的确同步了web端,写法也更流畅,在开发者工具中看是一切正常,跑在手机上则,只显示宽度的一半在各种机型下测试也是一样。

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