zoukankan      html  css  js  c++  java
  • 微信小程序 drawImage 问题

    好久没写了,其实可写的还是挺多,主要还是懒吧...

    最近公司项目使用小程序做序列帧动画,大概有 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 的话那当然有差距。

    总的来说,填坑的路是比较烦人的,

    后一个问题解决了又开始想,是不是前一个问题其实本来是对的,然后又回去重来一遍,

    最后的最后,来来回回,才能彻底填平这个坑。

  • 相关阅读:
    LeetCode 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/foreverZ/p/7365271.html
Copyright © 2011-2022 走看看