在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
好久没写了,其实可写的还是挺多,主要还是懒吧... 最近公司项目使用小程序做序列帧动画,大概有 116 张图,共9.6M。
比较闲的日子里实验了一番,主要有以下几种方法, 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 区别不大,方法名略有不同,再就是需要一个 draw 方法才会绘制。 canvas.getContext('2d') 等于 wx.createCanvasContext(canvas)。 一般 wx.createCanvasContext 放在 onReady 还是 onShow 并没有什么区别(手里机型太少,没试太多)
接着就开始了填坑之路: 1. 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 这个 api 最大并发限制为 10 个, 意味着直接 for 个 116 下是会报错的。 因此需要换用为递归的方式去预加载图片。 我写的递归不见得都适用,就不放出来了,应该没什么难点的。 (推荐先用 html 写通递归,不然小程序编辑器死循环了很扎心)
4. downloadFile 合法域名的配置 开发完成后出现了小程序仅有打开了调试工具才能正常运行的情况, 后来经过同事点拨,原来还要设置 downloadFile 的合法域名,这个修改就简单了。 每个月只能修改 5 次的限制应该不会造成什么影响。
5. requestAnimationFrame 问题 为了更好的动画优化,当然少不了 requestAnimationFrame 的存在。 然而,安卓机的小程序是有的,苹果机小程序却根本没有这个方法。 好在我们可以写段回退兼容,放在 Page 的外面。 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 的通信本身就不是多快的一件事,而如果单单只考虑 webview 和 html 的话那当然有差距。
总的来说,填坑的路是比较烦人的, 后一个问题解决了又开始想,是不是前一个问题其实本来是对的,然后又回去重来一遍, 最后的最后,来来回回,才能彻底填平这个坑。 |
请发表评论