【小程序】--------------处理canvas导出图片模糊问题-------------【劉】

时间:2024-02-25 10:24:56

一、业务需求:

    使用canvas在前端生成海报,并在海报上添加上水印。最后导出图片并保存到本地。

二、业务逻辑实现:

  (1)创建canvas画布======》(2)在canvas上绘制海报========》(3)绘制水印===========》(4)绘制完成,导出图片路径=========》(5)保存到本地,并可以分享,(长按保存图片)

三、代码实现:

  

(1)、创建画布并将图片和水印绘制到canvas上
const ctx = wx.createCanvasContext(\'myCanvas\'); ctx.drawImage("https://img******.jpg", 0, 0, 300, 400);
 ctx.drawImage("../../images/tools/water.png", ox, oy, ow, oh);
ctx.draw();

  网络图:

  如果是用网络图,则在模拟器上正常显示。则在手机上无法显示创建。

  因为canvas.drawImage 是不支持网络图片的,只支持本地图片。所以,任何网络图片都需要先缓存到本地,在通过 drawImage 调用储存的本地资源进行绘制,缓存通过 wx.getImageInfo实现。代码如下

let _that = this

wx.getImageInfo({
src: \'https://img******.jpg\',
success: function (res) {

    let width = res.width

    let height = res.height

    let type = res.type
    let path = res.path
    ctx.drawImage(path, 0, 0, 300, 400);
    ctx.drawImage("../../images/tools/water.png", 20, 20, 30, 40);
    ctx.draw()
  }

})

通过success回调函数可以获取网络图片的宽高路径,和图片的格式png、jpg、svg。。。。。。

 还有一点需要注意的是 draw 方法是异步的,如果图片还没加载成功,有可能画出来的是空的,所以 draw 方法后的回调导出图片

通过wx.canvasToTempFilePath

ctx.draw(true, (res) => {
wx.canvasToTempFilePath({
  x: 0,
  y: 0,
  width: 50,
  height: 50,
  destWidth: 100,
  destHeight: 100,
  canvasId: \'myCanvas\',
  success(res) {
    console.log(res.tempFilePath)
  }
})
 });

  

  保存图片到本地

通过wx.saveImageToPhotosAlbum将图片保存到本地

wx.saveImageToPhotosAlbum({
                filePath: res.tempFilePath,
                success(res) {
                  console.log("保存成功")
                  _that.showSaveSuccess()
                },
                fail() {
                  wx.showModal({
                    title: \'保存到相册失败\',
                    content: \'请点击图片,长按图片保存\',
                    showCancel: false
                  })
                }
              })

 

图片模糊问题

  然而,在导出图片时,那就是canvas生成的图片保存后很模糊。

  (1)、使用两个canvas进行绘图,一个canvas用于绘图展示。用另一个canvas设置和图片大小一样。用于导出图片时的绘制。设置opacity为0.不能设置display:none。

    问题:但实际上上这个方案有一点问题:其一,生成需要两个画布;其二,绘制过大画布在安卓上面会出现问题,官方文档里也提示了避免设置过大的宽高,在安卓下会有crash的问题。

  (2)、使用scale缩放画布,设置canvas的画布于图片大小一样。则用scale缩放到需要展示的大小。则在导出时不会出现模糊问题。

    问题:在模拟器上是没有问题的,但是在真机上调试是没有效果的。

  (3)、本质上就是生成一个更大的图片,因为手机的屏幕设备的像素比现在一般都是超过2的。实际上我们只需要在使用wx.canvasToTempFilePath的时候,设置参数destWidth和destHeight(输出的宽度和高度)为width和height的2倍以上即可。

    当然,这个具体数值也可以wx.getSystemInfo这个API来获取设备的像素比了(pixelRatio),这个像素比作为以上数值。

    在onLode函数中通过wx.getSystemInfo获取像素比(pixelRatio)。则在导出图片时需要设置

    destWidth:width * pixelRatio

    destHeight:height * pixelRatio