评论

[开盖即食]小程序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-09-22

    遇到大佬了,求问个问题。原贴传送门:https://developers.weixin.qq.com/community/develop/doc/0004a459fd8cc83dcffab96f051c00?jumpto=comment&commentid=000aa69d5d4a98aec0fa1b1885d0

    核心就是 canvas.createImage获得的image,在IOS中,image.src = xxx 单这一行的同步执行时间和图片大小成正比,要几百毫秒。

    大佬有遇到过吗,有没有什么解决思路呢

    2020-09-22
    赞同
    回复
  • Jacob
    Jacob
    2020-09-08

    up主问一下现在模拟器cover-view还是不能遮盖canvas(2d)吗?真机上没问题的,不是都支持同层渲染了吗

    2020-09-08
    赞同
    回复 2
    • 游戏人生
      游戏人生
      2020-09-08
      是同层渲染吗? map和live好像不行,map类有BUG,普通的canvas画板 IDE1.04 nightly版本我试了下,没问题
      2020-09-08
      回复
    • Jacob
      Jacob
      2020-09-08回复游戏人生
      好,我回去换nightly版本试试
      2020-09-08
      回复
  • 涂之包
    涂之包
    2020-09-04

    来人多的地方看看我的问题能不能解决:

    canvas2d 在企业微信中,IOS无法绘制图片,createImage后不走onload?

    https://developers.weixin.qq.com/community/enterprisewechat/doc/000ca8a9318ef0f823eabae5c55400

    2020-09-04
    赞同
    回复
  • 2020-08-30

    图片大一点就不绘制了, fillText渲染不出来字体,开发工具已经升级到最新,微信7.0.15,安卓手机秒退,canvas如果是在一个view上,visibility属性可以隐藏掉view背景,但是canvas显示

    2020-08-30
    赞同
    回复 3
    • 游戏人生
      游戏人生
      2020-08-30
      我之前也遇到过,建议是用 translate 移出屏幕的办法
      2020-08-30
      回复
    • 2020-08-30回复游戏人生
      新的api问题有点多, 不如老的好用
      2020-08-30
      回复
    • 游戏人生
      游戏人生
      2020-09-01回复
      新API最好的好处是 和源生JS保持一致,迁移起来方便,各有千秋吧
      2020-09-01
      回复
  • 欢乐马
    欢乐马
    2020-07-27

    最近我写了个小程序,也用到了canvas2d,在好多ios13,14的设备上都闪退了,楼主大大知道咋回事吗~这是项目地址:https://github.com/starkZH/LeonSans-WxAppComponent

    2020-07-27
    赞同
    回复 5
    • 2020-08-29
      安卓机也闪退
      2020-08-29
      回复
    • 游戏人生
      游戏人生
      2020-08-30回复
      ctx.font 写法的闪退? 先检查api的写法是否完整
      2020-08-30
      回复
    • 2020-08-30回复游戏人生
      完整的,ios是好的,ide也是好的,然后安卓机直接退出微信,而且我都没绘制多少东西,2个图片,2个字
      2020-08-30
      回复
    • 游戏人生
      游戏人生
      2020-08-31回复
      图片格式? base64吗?不应该呀,我看之前几个bug,官方都优化掉了
      2020-08-31
      回复
    • 2020-08-31回复游戏人生
      一个base64, 一个png, 还有一个问题,fs.writefile写的文件,写成功了,回调给的链接访问报错,也是醉了。
      2020-08-31
      回复
  • 假年儿
    假年儿
    2020-07-20

    话说因为是同层,所以阻塞了渲染进程有好的法子吗TAT,已经分帧画图了(目前需求是上传前压缩图片,修改尺寸)

    2020-07-20
    赞同
    回复 2
    • 游戏人生
      游戏人生
      2020-07-20
      如果上传的是JPG 有官方的压缩方法,至于阻塞进程? 会闪退吗? 还是说async和await的方法? 另外canvas 最好不要叠加
      2020-07-20
      回复
    • 假年儿
      假年儿
      2020-07-21回复游戏人生
      闪退目前没有发现,这里用canvas主要压缩的是尺寸,
      2020-07-21
      回复
  • 揽风
    揽风
    2020-05-26

    楼主我想问下,为什么我这个保存图片的时候会报错

    2020-05-26
    赞同
    回复 3
    • 游戏人生
      游戏人生
      2020-05-26
      初步看,问题是出在 canvas 对象上,如果你用新方法,必须是一个当前获取的对象,和之前老方法中canvas的ID方式不同,你先试下文章中的获取的方法,必须是 await 同步方法,我们先排除法一个个看下
      2020-05-26
      回复
    • 揽风
      揽风
      2020-05-26回复游戏人生
      我传错对象了,是要把那个node值传到canvas里面就可以了
      2020-05-26
      回复
    • 游戏人生
      游戏人生
      2020-05-26回复揽风
      嗯,问题解决就好
      2020-05-26
      回复
  • 。
    2020-05-16

    2020-05-16
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-05-17
      你用的是京东的taro,这个第三方的框架,我没用过,不太确定,不过原生的方法节点是  res[0].node,不是res.node
      2020-05-17
      回复
  • 韦不吕
    韦不吕
    2020-05-14

    我遇到的问题:使用canvas 2D,PC开发工具可以绘制canvas,可以保存为图片。手机上预览canvas无法绘制出图片,只有一片区域。

    2020-05-14
    赞同
    回复 4
    • 游戏人生
      游戏人生
      2020-05-15
      有代码段吗?。。。这个我很难脑补问题啊
      2020-05-15
      回复
    • 韦不吕
      韦不吕
      2020-05-15回复游戏人生
      谢谢关注。我是做的页面截图。做了更多测试发现页面比较短就可以绘制,长了就是空白。旧的canvas可以做长截图。新不如旧。看看原厂怎么演进吧。
      2020-05-15
      回复
    • Z_浩南
      Z_浩南
      2020-07-08
      可能是这段代码执行了多次
      2020-07-08
      回复
    • Z_浩南
      Z_浩南
      2020-07-08
      可能是这段代码执行了多次
      2020-07-08
      回复
  • 韦不吕
    韦不吕
    2020-05-12

    请教怎样得到android版本和ios微信当前的字体?

    2020-05-12
    赞同
    回复 1
    • 游戏人生
      游戏人生
      2020-05-14
      当前字体? 就是IOS默认的字体,这个可以问google下,我记得中文是“苹方字体”,因为几个经典字体都支持。Android 不清楚
      2020-05-14
      回复

正在加载...

登录 后发表内容