小程序开发canvas踩过的坑

小程序开发中,如果需要做一些生成海报 / 插入文字.图片的功能,这个时候canvas控件可以实现你想要的效果。基础的用法我就不多说了,难度系不高,下面说两个我使用canvas做海报功能的时候遇到的3个大坑和多行文本绘制。

1.canvas中使用 canvas.drawImage() 方法

小程序中canvas.drawImage(imagePaht, 0, 0, 100, 100)里面,添加画布基础图片只有两种方式:
第一种:把图片加载到小程序文件夹中,直接通过image路径调用。(图片少且小可以使用)
第二种:使用云端存储的图片地址。(图片多且大使用url图片)
使用第二种方式会出现一个问题,canvas.drawImage()不支持直接使用url图片地址,不会报错,画布只会出现绘制上去的图片/文字,没有url基础图片。这个时候我们需要绕过这个url的方法,把图片下载到本地缓存,然后取出来使用,看下面代码。

//url图片下载到本地
  wx.downloadFile({
    url: "https://www.image.com", 
    success: function (sres) {
      console.log(sres.tempFilePath);
      //确保图片已下载到本地,再开始进行canvas操作
      if (sres.tempFilePath){
        that.createNewImage(sres.tempFilePath);
      }
    }, fail: function (fres) {
    }
 })

/* 处理图片/文字绘制 */
  createNewImage: function (urlPath){
    var that = this;
    var content = wx.createCanvasContext('mycanvas')
    // 把模板图片绘制到canvas上
    content.drawImage(urlPath, 0, 0, 750, 2540);//使用下载的本地图片
    this.setCarName(content);
    content.draw();//绘制图片
    
    //把生成好的图片保存到本地
    xxxxxxxxxxxxxxxxxxxxxxxxx
  },

 

2.canvas绘制的海报图片和想要的效果不一致

一般会出现两种情况,第一海报只展示了一部分,第二画布上的文字/图片位置没有出现在规定的位置,问题出在wxml中canvas的大小 和js中 canvas.drawImage()大小设置不一致,看代码
wxml:

<view class='canvas-box'>
  <canvas style='width:750px; height:2540px' canvas-id='mycanvas'></canvas>
</view>

js:

canvas.drawImage(urlPath, 0, 0, 750, 2540);

 

3.安卓设备使用canvas崩溃

canvas绘制的时候有使用大图进行绘制的场景,这个时候发现一个奇怪的问题,ios系统加载大图绘制没毛病,安卓设备刚进页面就crash,不管安卓设备多牛逼还是会crash。这个时候需要好好看下官方组件,Bug中明确说到“避免设置过大的宽高,在安卓下会有crash的问题”,所以要好好看文档,毕竟ios和安卓不是一个妈生的。
安卓设备到底多大会crash呢,我给一个大概的数字“1200px / 4000px”,在这个范围内应该是安全的。
iOS设备多大会crash呢,我也不知道啊!我设置了“1920px / 9420px”大小的canvas,这么大的像素一点毛病都没有,大家可以试试看极限在哪里。

 

4.canvas绘制多行文本

canvas中绘制多行文本,并不能自动实现文本换行。文本的高度和宽度,换行的位置都需要我们自己处理,下面介绍两种情况换行处理。
代码如下:

var str = this.data.importDta.textarea;
var color = app.changeRgbColorToHex('rgb(254, 250, 169)');
var canvasWidth = 550;//计算canvas的宽度
var initHeight = 2200;//绘制字体距离canvas顶部初始的高度

content.setFontSize(60);//文本字体大小
content.setFillStyle(color);//文本字体颜色
this.drawText(content, str, initHeight, canvasWidth);//文本换行显示处理方法
content.stroke();
(1)无换行符

整段文字,固定宽高显示区域自动换行

/**
    * 绘制多行文本
    * @param content  canvas对象
    * @param str 文本内容
    * @param initHeight 文本绘制在画布中的初始高度
    * @param canvasWidth 文本绘制的最大宽度
*/
drawText: function (content, str, initHeight, canvasWidth) {
    var lineWidth = 0;
    var lastSubStrIndex = 0; //每次开始截取的字符串的索引
    for (let i = 0; i < str.length; i++) {
      lineWidth += content.measureText(str[i]).width;
      if (lineWidth > canvasWidth) {
        content.fillText(str.substring(lastSubStrIndex, i), 420, initHeight);//绘制截取部分
        initHeight += 70;//60为字体的高度
        lineWidth = 0;
        lastSubStrIndex = i;
      }
      if (i == str.length - 1) {//绘制剩余部分
        content.fillText(str.substring(lastSubStrIndex, i + 1), 420, initHeight);
      }
    }
}
(2)有换行符

文字中间有换行符 \n , 自动换行+换行符换行

/**
    * 绘制多行文本
    * @param str 文本内容
    * @param leftMargin 文本绘制的初始左边距
    * @param initHeight 文本绘制的初始高度
    * @param canvasWidth 文本的宽度
  */
  //有“\n”换行符的处理方式
  drawText: function (content, str, leftMargin, initHeight, canvasWidth) {
    var lineWidth = 0
    var lastSubStrIndex = 0; //每次开始截取的字符串的索引
    for (let i = 0; i < str.length; i++) {
      lineWidth += content.measureText(str[i]).width
      
      if (str[i] == "\n") {
        content.fillText(str.substring(lastSubStrIndex, i), leftMargin, initHeight);//绘制截取部分
        initHeight += 84//文字+间距的高度
        lineWidth = 0
        lastSubStrIndex = i + 1;
      }else if (lineWidth > canvasWidth) {
        content.fillText(str.substring(lastSubStrIndex, i), leftMargin, initHeight);//绘制截取部分
        initHeight += 84//文字+间距的高度
        lineWidth = 0
        lastSubStrIndex = i
      }
      
      if (i == str.length - 1) {//绘制剩余部分
        content.fillText(str.substring(lastSubStrIndex, i + 1), leftMargin, initHeight);
      }
    }
  }

目前只发现这三个坑,后面有坑会继续补充,希望大家能够合理的避开这三个坑,写出优秀的小程序应用!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容