评论

[开盖即食]小程序Canvas官方新版API实战

Canvas 2D 2.9.0 新版API实战, 请注意:官方目前不支持真机调试!!! 只能预览



最近本人在开发一个新项目的时候,注意到官方在2.9.0开始支持了一个canvas 2D的新API,同时对webGL上支持也有了很大的改进,相信很多人用canvas的组件做一些分享海报,战绩和新闻帖功能。

这里是新的引入方式。
官方文档地址:
https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html

那么新的canvas2D API有啥好处呢?

  • 原本的API微信有做一定的修改,现在全面支持源生H5 JS的写法,迁移H5的老代码变成更加容易,学习成本更低
  • 修复了一些诡异的BUG,例如原本在IOS早期版本写法顺序会导致clip()图片裁切失效等~
  • 性能上的优化和提升,复杂动画上帧数明显

举例写法上的一些改变:

1、设置font的写法:

//原本(传值的写法)
ctx.setFontSize(20);
ctx.fillText('MINA', 100, 100)
ctx.draw()

//现在(和源生H5写法一致,赋值)
ctx.font = "16px";
ctx.fillStyle = 'blue'; //可以直接写颜色,原本的不支持
//不需要 ctx.draw()

2、获取并添加图片写法:

//原本
//使用的是 wx.getImageInfo的方法
wx.getImageInfo({
    src: mainImg,//服务器返回的图片地址
    success: function (res) {
        console.log(res);
        ctx.drawImage(res.path, 0, 0);
        ctx.draw(true);
    },
    fail: function (res) {
        //失败回调
    }
});

//现在
//可以直接img.onload调用
const headerImg = canvas.createImage();
headerImg.src = headImage;//微信请求返回头像
headerImg.onload = () => {
    ctx.save();
    ctx.beginPath()//开始创建一个路径
    ctx.arc(38, 288, 18, 0, 2 * Math.PI, false)//画一个圆形裁剪区域
    ctx.clip()//裁剪
    ctx.drawImage(headerImg,0,0);
    ctx.closePath();
    ctx.restore();
}

3、将canvas生成虚拟地址便于下载(重点):


由于官方文档没有写清楚,误导了挺多人的。这里canvas对象必须通过选择器获取,并获得对应的node节点。

async saveImg() {
    let self = this;
    //这里是重点  新版本的type 2d 获取方法
    const query = wx.createSelectorQuery();
    const canvasObj = await new Promise((resolve, reject) => {
      query.select('#posterCanvas')
        .fields({ node: true, size: true })
        .exec(async (res) => {
          resolve(res[0].node);
        })
    });
    console.log(canvasObj);
    wx.canvasToTempFilePath({
      //fileType: 'jpg',
      //canvasId: 'posterCanvas', //之前的写法
      canvas: canvasObj, //现在的写法
      success: (res) => {
        console.log(res);
        self.setData({ canClose: true });
        //保存图片
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success: function (data) {
            wx.showToast({
              title: '已保存到相册',
              icon: 'success',
              duration: 2000
            })
            // setTimeout(() => {
            //   self.setData({show: false})
            // }, 6000);
          },
          fail: function (err) {
            console.log(err);
            if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
              console.log("当初用户拒绝,再次发起授权")
            } else {
              util.showToast("请截屏保存分享");
            }
          },
          complete(res) {
            wx.hideLoading();
            console.log(res);
          }
        })
      },
      fail(res) {
        console.log(res);
      }
    }, this)
  },

分享个canvas海报的代码片段:

片段名: PoCf4emw7TgE

片段link:
https://developers.weixin.qq.com/s/PoCf4emw7TgE



总结,相对之前还要看官方文档的canvas自定义API,现在写起来更加的方便,老代码迁移起来得心应手,只要你之前会canvas,那么各种效果和动画,拿来就怼,没什么大问题~

一些奇怪的问题(注意!!!)

  1. canvas 2d 目前(2020年4月3日)还不支持真机调试,会报错!!!
  2. IDE工具 1.02.2003190 直接保存新版本canvas的API图片是打不开的,但是直接用手机保存在相册是没问题的,请更新到1.02.2003250 最新版即可解决~
  3. 一些老款手机用新的API保存图片会有报错问题,如华为NOTE10,请更新系统到能支持的最新,且微信也是,即可解决~
  4. 部分Android设备诡异的闪退和报错

    这种有可能是代码写法的问题,比如:
//缺省写法  会导致部分Android机器 闪退
ctx.font = "bold 16px";
ctx.fillStyle = "#000"

//在canvas 2D的写法中,所以写法必须规范且完整
ctx.font = "normal bold 12px sans-serif";  
ctx.fillStyle = '#707070'; 

所以在canvas 2D 的环境,所以写法必须原始且规范,不能用缺省写法,不然就会有诡异的闪退/报错。
后续:官方在7.0.13的Android版本已修复。
https://developers.weixin.qq.com/community/develop/doc/00088c13e1437890692afd8d85ec00

看完觉得有帮助记得点个赞哦~

你的赞是我继续分享的最大动力!^-^

最后一次编辑于  2020-05-09  
点赞 44
收藏
评论

30 个评论

  • 傷
    2020-05-12

    canvas动画闪退怎么解决啊?

    2020-05-12
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-05-14
      微信更新到最新7.0.13版本,IDE工具更新到最新,再看下,之前一些妖怪BUG基本都解决了
      2020-05-14
      回复
  • 世界尽头
    世界尽头
    2020-05-09

    另外补充一个安卓闪退的情况:

    ctx.font = "normal bold 12px sans-serif";

    这里面的字体如果设置比较特殊的(或者说在手机上没有这个字体,具体不太确定),如 PingFangSC-Regular、PingFang SC,也会在安卓手机闪退。

    2020-05-09
    赞同
    回复 7
    • 游戏人生
      游戏人生
      2020-05-09
      粗体和闪退 这个问题现在已经修复了,我们公司的小米和华为升级到7.0.13微信 就好了。至于你列出来的那个特殊字体,我没试过,不做评论
      2020-05-09
      回复
    • 游戏人生
      游戏人生
      2020-05-09
      建议检查下微信版本和基础库
      2020-05-09
      回复
    • 世界尽头
      世界尽头
      2020-05-09回复游戏人生
      感谢回复。升级微信到 7.0.13 后,设置特殊的字体确实不会闪退了。但是又有一个奇怪的问题,就是字体大小又不生效了(测试手机:小米 8,系统是 MIUI 11,Android 10)。另外无论怎么设置字体,在真机上字体粗细都不生效。模拟器一切正常。
      我对比了一下我的写法跟您帖子里的写法,唯一的区别就是我的代码中字体大小有个 rpx 转 px,不确定是不是由于转换的结果有小数之类的导致的问题。
      2020-05-09
      回复
    • 世界尽头
      世界尽头
      2020-05-09
      补充一个真机和模拟器对比图。左边真机,右边模拟器。
      ctx.font = 'normal bold 36px sans-serif';
      2020-05-09
      回复
    • 游戏人生
      游戏人生
      2020-05-09回复世界尽头
      上面数字是加粗的吧?就文字不加粗? 你身边有其他Android机器可以对比测试吗?  公司的小米 9p我测过最新版本是好的,可以加粗
      2020-05-09
      回复
    查看更多(2)
  • 世界尽头
    世界尽头
    2020-05-09

    真机粗体不生效有解决办法吗?模拟器显示正常,但是在真机上目测只有数字生效了。

    2020-05-09
    赞同
    回复 2
    • 游戏人生
      游戏人生
      2020-05-09
      设备型号是?
      2020-05-09
      回复
    • 世界尽头
      世界尽头
      2020-05-09回复游戏人生
      小米 8,iPhone X 均无法生效粗体。
      2020-05-09
      回复
  • guo
    guo
    2020-04-28

    OPPO R11,写了个ctx.font = "12px 微软雅黑",闪退了,忘了大佬这篇文章提醒了,已剁手惩戒/(ㄒoㄒ)/~~

    2020-04-28
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-04-28
      没事,找到原因避免就好
      2020-04-28
      回复
  • 在劫难逃的天真
    在劫难逃的天真
    2020-04-21

    剪裁圆形 对png格式的图不生效么?

    2020-04-21
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-04-28
      生效的。是这样的,之前有类似的BUG,但是在最新微信版本已修复
      2020-04-28
      回复
  • 炎峰森林影
    炎峰森林影
    2020-04-21

    官方编辑器v1.02.1911180,保存图片失败

    2020-04-21
    赞同
    回复 4
    • 炎峰森林影
      炎峰森林影
      2020-04-21
      找到坑了,必须添加宽高度,否则总是保存失败
      2020-04-21
      回复
    • 游戏人生
      游戏人生
      2020-04-21回复炎峰森林影
      嗯嗯,nightly版本IDE工具 最近还有web-view的bug,谨慎更新
      2020-04-21
      回复
    • 炎峰森林影
      炎峰森林影
      2020-04-27回复炎峰森林影
      写给大家:


      第一点:
      经测试仅加上width,height是不行,在ios使用wx.canvasToTempFilePath保存会变形,为了防止出现,只能将x,y,width,height,destWidth,destHeight全部设置!


      // ==============================


      第二点:
      const canvas = res[0].node;
      const ctx = canvas.getContext("2d");


      const dpr = uni.getSystemInfoSync().pixelRatio; 

      canvas.width = Math.ceil(res[0].width * dpr);
      canvas.height = Math.ceil(res[0].height * dpr);
      ctx.resetTransform();      // 强烈建议在scale前加上这句(如果在onShow上生成海报必须要)
      ctx.scale(dpr, dpr);
      ctx.save();
      2020-04-27
      回复
    • 炎峰森林影
      炎峰森林影
      2020-04-28回复炎峰森林影
      巨坑,ios微信没有ctx.resetTransform(),安卓却正常,根据火狐mdn社区用ctx.setTransform(1, 0, 0, 1, 0, 0)代替就好了
      2020-04-28
      1
      回复
  • 无说
    无说
    2020-04-09

    太强了

    2020-04-09
    赞同
    回复
  • 木帆船
    木帆船
    2020-03-30

    问下,在第二点中,新的写法下载图片是不是不再受download域名限制了?

    2020-03-30
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-03-30
      是! 兄弟。。。你知道的太多了。。。这个想法多想很危险~
      2020-03-30
      回复
  • 微蓝色雪狐
    微蓝色雪狐
    2020-03-30

    很多接口是很不错,但是有时考虑到一些用户微信没有升级。其它有一些接口是用不到。我已经修改到烦燥了!最后所有海报后台生成。暂不考虑前端生成

    2020-03-30
    赞同
    回复 14
    • Admin ²º²⁴
      Admin ²º²⁴
      2020-03-30
      后台生成是最优方案,生成过N张海报尝试过N种方案的飘过。特别适用于经常更换图片样式的,比如那些XX节日的时候需要生成XX节日专用背景的方案。后端稍稍一改就好了。小程序端不用维护代码,不用提审。
      小程序的canvas的坑目前还是填不完的状态。楼主这代码片段有兴趣测试下,是生成失败的
      2020-03-30
      回复
    • 游戏人生
      游戏人生
      2020-03-30
      我这里也填了好久的坑,似乎IDE工具没完全适配到新版canvas API的修改上,但是从我上线项目来看,Android老机器有些保存的BUG,其他ios和高版本的Android机暂时没发现什么问题
      2020-03-30
      回复
    • Admin ²º²⁴
      Admin ²º²⁴
      2020-03-30
      还有基础库的要求。你真要全适配,你要兼容旧版本基础库,旧版本的你得继续用原版的canvas来画,意味着你要写2份代码,除非你放弃掉旧版本的基础库用户
      2020-03-30
      回复
    • 游戏人生
      游戏人生
      2020-03-30回复Admin ²º²⁴
      我又重新测了下,华为note10更新到能支持的最大Android版本,微信也是,保存既没有了,另外IDE工具更新到最新版本 1.02.2003250 也可解决生成问题~
      2020-03-30
      回复
    • Admin ²º²⁴
      Admin ²º²⁴
      2020-03-31回复游戏人生
      恩,这样很有意义。
      2020-03-31
      回复
    查看更多(9)
  • 小满
    小满
    2020-03-30

    点赞,大佬

    2020-03-30
    赞同
    回复

正在加载...

登录 后发表内容