javascript手把手教你绘制小程序海报wang013

constcontext=uni.createCanvasContext('posterId');图片支持远程图片和本地图片,网络图片要通过getImageInfo/downloadFile先下载。

context.drawImage('/static/poster.png',0,0,320,410);//绘制背景图片constavatarLeft=185;constavatarTop=18;constavatarWidth=16;constavatarHeight=16;context.drawImage('/static/avatar.png',avatarLeft,avatarTop,avatarWidth,avatarHeight);从设计上来看头像和昵称是对齐的。

直接按照设计稿距离来设定看看效果

constnickName='墙头草中的顶尖的';constnameLeft=avatarLeft+avatarWidth+7;context.setFillStyle('#ffffff');context.setFontSize(12);context.fillText(nickName,nameLeft,21,96);实际效果如下:

发现与预期效果对应不上,思考下这是为什么?文字设置距离偏移的参考基线不是文字的顶部。

怎么验证我的说法呢?可以x值设置为0。

constnickName='墙头草中的顶尖的';constnameLeft=avatarLeft+avatarWidth+7;context.setFillStyle('#ffffff');context.setFontSize(12);context.fillText(nickName,nameLeft,0,96);//修改为0再看看效果:

发现参考点几乎是文字的底部,这就验证了上面的结论。

怎么解决这个问题呢?

通常知道文本行实际占用的高度,需要知道其line-height,上面并不知道其line-height值。canvas本身并不直接支持line-height属性,显然没办法获得相对准确的行高。

只能采用第二种方式,从canvas提供API来看,可以更改文本相行对齐的点。

constnickName='墙头草中的顶尖的';constnameLeft=avatarLeft+avatarWidth+7;context.setFillStyle('#ffffff');context.setFontSize(12);context.setTextBaseline('top');//更改基线对齐点context.fillText(nickName,nameLeft,21,96);再来看看效果如下:

接下来实现二维码区域,主要白色背景+二维码+文案

constrectWidth=300;constrectHeight=89;constrectLeft=10;constrectTop=311;context.setFillStyle('#ffffff');context.fillRect(rectLeft,rectTop,rectWidth,rectHeight);效果如下:

constqrcodeLeft=20;constqrcodeTop=rectTop+10;constqrcodeWidth=68;constqrcodeHeight=68;context.drawImage('/static/qrcode.png',qrcodeLeft,qrcodeTop,qrcodeWidth,qrcodeHeight);二维码这里直接采用现成图片。实际上前端可以通过weapp.qrcode.esm.js在前端生成二维码,再把它绘制上去。

conststartX=qrcodeLeft+qrcodeWidth+15;consttext1='与志同道合的,他们一起成长';context.setFillStyle('#161413');context.setFontSize(14);context.setTextBaseline('top');context.fillText(text1,startX,rectTop+29);consttext2='扫码即可进入“Get一下”社区';context.font='bold14pxArial';context.fillText(text2,startX,rectTop+51);看看最后的效果:

左上角的部分没有绘制,思路同头像和昵称一样。接下来只要把图片保存到相册即可。

在小程序中,提供方法支持如下:

constonSave=()=>{//转换为临时路径uni.canvasToTempFilePath({canvasId:'posterId',success:(res)=>{//保存图片到相册uni.saveImageToPhotosAlbum({filePath:res.tempFilePath,success:()=>{uni.showToast({title:'保存成功',icon:'none',});},fail:()=>{uni.showToast({title:'保存失败',icon:'none',});},});},});};这里基本上把一个海报绘制

constnickName='墙头草中的顶尖的墙头草中的顶尖的';constnameLeft=avatarLeft+avatarWidth+7;context.setFillStyle('#ffffff');context.setFontSize(12);context.fillText(nickName,nameLeft,21,96);

从效果来看,发现文字直接重叠。如果希望超出的部分能够通过省略号来省略,是可以的

constnickName='墙头草中的顶尖的墙头草中的顶尖的';constnameLeft=avatarLeft+avatarWidth+7;context.setFillStyle('#ffffff');context.setFontSize(12);context.fillText(nickName,nameLeft,21,96);lettext='';consttextArr=nickName.split('');constellipsisWidth=context.measureText('...').width;//省略号的宽度for(leti=0;i96){text=text+'...';break;}text=temp;}context.fillText(text,nameLeft,21,96);上面主要是通过measureText方法获得文字对应宽度,针对超出的部分采用省略号替代。当然,如果希望完整地显示名字,也可以使用换行的方式。具体的实现方式,就留给大家自己思考和实现了。

处理后效果如下:

默认采用圆角头像,如果用户上传的头像没有进行裁剪处理,导致图片出现非圆角情况,那么在海报上呈现的效果可能会有所差异。

先使用一个非圆角的图片,代码修改如下:

constavatarLeft=185;constavatarTop=18;constavatarWidth=16;constavatarHeight=16;context.drawImage('/static/avatar-rect.png',avatarLeft,avatarTop,avatarWidth,avatarHeight);效果如下:

现在对图片处理一下:

constavatarLeft=185;constavatarTop=18;constavatarWidth=16;constavatarHeight=16;context.beginPath();context.arc(avatarLeft+avatarWidth/2,avatarTop+avatarHeight/2,avatarWidth/2,0,2*Math.PI);context.closePath();context.clip();//绘制圆形头像context.drawImage('/static/avatar-rect.png',avatarLeft,avatarTop,avatarWidth,avatarHeight);效果如下:

圆角是实现了,发现其他区域内容都被裁剪了。这是为什么?clip()改变了绘画环境。ctx()调用后,所裁剪的区域就是clip()后的绘制环境,clip()之后的绘画只能在裁剪区域中渲染,不能访问画布上的其他区域。

怎么处理这个问题呢?通过save()和restore().

context.save();//暂存context.beginPath();context.arc(avatarLeft+avatarWidth/2,avatarTop+avatarHeight/2,avatarWidth/2,0,2*Math.PI);context.closePath();context.clip();//绘制圆形头像context.drawImage('/static/avatar-rect.png',avatarLeft,avatarTop,avatarWidth,avatarHeight);context.restore();//恢复

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