在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轴的推移)
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端,写法也更流畅,在开发者工具中看是一切正常,跑在手机上则,只显示宽度的一半在各种机型下测试也是一样。