微信小程序 drawImage 问题

最近公司项目使用小程序做序列帧动画,大概有 116 张图,共 7.4M。

比较闲的日子里实验了一番,主要有以下几种方法,

  1. css background-image + animation
  2. css background-position + animation
  3. js background-image
  4. js background-position
  5. js img src
  6. canvas drawImage

结果当然是 canvas 性能最优咯,不会出现掉帧和卡屏的情况,其中最不推荐第一种

所以这次项目也就准备尝试下微信小程序的 canvas 会不会有别样的风味。
基本上和 html 的 canvas 区别不大,方法名略有不同,
canvas.getContext('2d') 等于 wx.createCanvasContext(canvas)
再就是需要一个 draw() 方法才会绘制(经常容易忘记)。
至于 wx.createCanvasContext 放在 onReady 还是 onShow,以及重复新建等问题上,由于项目紧凑,手里机型太少,没试太多


接着就开始了填坑之路:

一. Image 对象问题,只需直接使用图片路径

官方案例给的是 wx.chooseImage 返回的缓存文件,显然不是我们要的;
在 HTML 中如果想 drawImage 那就需要一个 Image 对象,需要先 new Image() 或者获取到 DOM 中的 <img>
那么小程序该怎么办呢,我略一沉凝,准备试它一试,直接使用了图片绝对路径,

ctx = ctx ? ctx : wx.createCanvasContext('imgs');
url = 'https://sum.kdcer.com/test/sw_shake/0/0 (1).jpg';
ctx.drawImage(url, 0, 0, 300, 500);  // 直接使用图片路径
ctx.darw()

调试器上是正常的。url 为相对路径也是可以的。
当然,这个时候预加载就是个问题,只能在 wxml 中去 for 出所有的图片并 bindload 了。

2. 图片路径不能有特殊符号

上面的情况虽然调试器中可看,但手机预览时还是没有任何图片绘制上去呀(其他点线绘制是存在的),所以我怀疑仅仅是图片或小程序的问题。
然后去论坛博客寻找了番,不禁感叹资料可真少啊。

另一方面,我准备再试试 downloadFile 这种方法。

wx.downloadFile({
  url: url,
  success: function (res) {
    ctx.drawImage(res.tempFilePath, 0, 0, 300, 500);
    ctx.draw();
  }
})

结果返回给我的 res.tempFilePath 是个 .htm 结尾的文件,报出 http 400(请求无效)的错误。

我怀疑问题出在了文件本身,于是我改了下文件名,由 0 (1).jpg 改为 1.jpg,就能正常访问了。
再后来进行了一些实验,暂时还只发现了 空格+括号 这一种命名会失败。

返回去再试一次, drawImage 直接使用命名正确的图片绝对路径其实是可以的,
只是还是那个小问题,加载得慢的话,图片异步没法绘制上去了,需要预加载。
所以更为推荐使用 downloadFile 这种方式来先加载图片再绘制。

比较坑的是,downloadFile 不能下载相对路径的图片,
这让我想优化把一部分图片放进小程序变得无比麻烦。
(其实 2M 资源放进去小程序就会变得非常卡,不推荐)

3. downloadFile 文件数限制

官方表示,downloadFile 最大并发限制为 10 个,
意味着直接 for 个 116 下是会报错的。
因此需要换用为递归的方式去预加载图片。

我写的递归不见得都适用,就不放出来了,应该没什么难点的。
(推荐先用 .html 写通递归,不然小程序编辑器死循环了很扎心)

4. downloadFile 合法域名的配置

开发完成后出现了小程序仅有打开了调试工具才能正常运行的情况,
后来经过同事点拨,原来还要设置 downloadFile 的合法域名,这个修改很简单。

回到调试器记得重启一次项目或者在预览页的配置 tab 中刷新一次。

每个月只能修改 5 次的限制应该不会造成什么影响。

5. requestAnimationFrame 问题

为了更好的动画优化,当然少不了 requestAnimationFrame 的存在。
然而,安卓机的小程序是有的,苹果机小程序却根本没有这个方法。

好在我们可以写段回退兼容:

if (typeof requestAnimationFrame == 'undefined') {
  var lastTime = 0;
  var requestAnimationFrame = function (callback) {
    var currTime = new Date().getTime();
    var timeToCall = Math.max(0, 16 - (currTime - lastTime));
    var id = setTimeout(function () { callback(currTime + timeToCall); }, timeToCall);
    lastTime = currTime + timeToCall;
    return id;
  };
}
if (typeof cancelAnimationFrame == 'undefined') {
  var cancelAnimationFrame = function (id) {
    clearTimeout(id);
  };
}

6. fps 性能问题

小程序一直吹嘘着接近原生的流畅体验,但这次帧动画的项目中显然打脸了。
html 版的 canvas 每 15ms 绘制一次都是小 case,
但小程序则需要 50ms 以上的间隔。否则会出现间断性白屏。

60fps 和 20fps 虽然在 html 中有很大差距,
但在小程序中 20fps 并没有太影响用户的浏览体验。
毕竟 js 的运算和 webview 的通信本身就不是多快的一件事,
而如果单单只考虑 webviewhtml 的话那当然有差距。

7. canvas 在小程序层叠上下文层级非常高

canvas / video / map 在小程序中的 z 轴层级非常高,甚至能盖过调试工具。
所以我们想在他们上面再叠一些元素就只能靠 cover-view 了。

但是,cover-view 只支持基本的定位、布局、文本样式,
不支持设置单边的 borderopacitybackground-image 等。
我觉得不能叠图这个问题还是有些麻烦的,至少操作起来是这样。
而且,cover-view 暂不支持 css 动画。

事件不会冒泡到 canvas 及其父级,影响暂时感觉不大。

8. 小程序的 drawImage 不支持9个参数的传参

不过有人去改了编辑器源码,见 we_flappybird
测了可行,但并不推荐,编辑器下次更新又要改。


总的来说,填坑的路是比较烦人的,
后一个问题解决了又开始想,是不是前一个问题其实本来是对的,然后又回去重来一遍,
最后的最后,来来回回,才能彻底填平这个坑。

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

推荐阅读更多精彩内容