1

wx.canvasToTempFilePath

众所周知,微信canvas生成图片要调用这个接口,而这个接口如果想生成高清的图片,解决字体模糊问题则需要destWidth * dpr

原始canvas的宽高过大,再加上destWidth * dpr必然会导致destWidth的宽高过大,从而可能导致安卓在生成图片时失败。

既然这个接口行不通,那么就不使用这个接口啦。

换个思路,小程序canvas type=2d 接口,支持的基础库也比较全面了,根据官方介绍说,canvas type=2d基本上参照了H5的接口,那么,H5可用的方法,在这里应该可以使用了。

canvas 2d

根据微信提供的示例:

Page({
  onReady() {
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({ node: true, size: true })
      .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        const dpr = wx.getSystemInfoSync().pixelRatio
        canvas.width = res[0].width * dpr
        canvas.height = res[0].height * dpr
        ctx.scale(dpr, dpr)
        ctx.fillRect(0, 0, 100, 100)
      })
   }
})

canvas 2d要想绘制高清,同时文字不模糊,则需要将canvas.width和canvas.height显式的设置并乘dpr(wxss也要正常设置正常宽高),同时需要将绘制上下文ctx缩放dpr。

ctx缩放dpr是为了让绘制密度与像素密度保持一致。如果某些东西不想缩放绘制,则可以设置ctx.setTransform(1, 0, 0, 1, 0, 0)还原绘制上下文的缩放。

现在大胆绘制吧,因为绘制的密度等于像素密度,所以实际显示是非常清晰的,canvas 2d的宽高可以设置较大,但不能设置过大哦,过大的宽高,在安卓下会有crash的问题。

真机测试1500800的宽高是完全没有问题的,由于像素密度的原因,假如dpr = 3,实际上是45002400

那么这么大的宽高在使用wx.canvasToTempFilePath时很有可能造成安卓真机生成图片失败,这时候就应该祭出一个神器:

_canvas_.toDataURL(_type_, _encoderOptions_);

HTMLCanvasElement.toDataURL() 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为96dpi。

  • type 可选,图片格式,默认为 image/png
  • encoderOptions 可选,在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。

可以通过canvas.toDataURL()得到一个含图片展示的data URI,通过删除头data:image/jpeg;base64,得到一个纯base64的图片数据。

既然得到图片数据了,那么,将数据写入成图片就可以了。

  • 打开微信提供的文件管理器
  • 将base64数据转换为buffer
  • 通过fsm.writeFile将文件写入用户存储空间wx.env.USER_DATA_PATH位置。
  • filePath就是图片啦
  • 由于微信的存储空间只有10M,所以最大可以支持10M的图片生成哦,可以满足多数需求了。
const filePath = `${wx.env.USER_DATA_PATH}/cover.jpg`;
let fsm = wx.getFileSystemManager();
let buffer = wx.base64ToArrayBuffer(bodyData);
fsm.writeFile({
     filePath: filePath,
     data: buffer,
     encoding: 'binary',
     success() {
         console.log('---success---', filePath);
     },
     fail(error) {
        console.error(error);
     }
 });

使用完别忘了清理存储空间,不然下次存不进去

  removeLocalFile() {
    // 注意,文件存储空间为10M
    // 为了保持空间够用,删除了根目录下的文件
    const fsm = wx.getFileSystemManager();
    try {
      const ls = fsm.readdirSync(wx.env.USER_DATA_PATH);
      ls.forEach(d => {
        let path = `${wx.env.USER_DATA_PATH}/${d}`;
        let stats = fsm.statSync(path);
        if (stats.isFile()) {
          fsm.unlinkSync(path);
        }
      });
    } catch (e) {
      console.log(e);
    }
  }

可以根据需求清空不同的文件,没必要清空根目录所有内容

至此,可以愉快的使用canvas2d绘制高清图片了。


fyuan
78 声望2 粉丝

js开发者