微信小程序canvasToTempFilePath:fail fail canvas is empty
如默
撰写于 2024年 09月 10 日

说明

如题,最近在写一个小程序时,canvas报错,canvasToTempFilePath:fail fail canvas is empty,记录一下如何修复

步骤

首先吐槽一句,微信小程序官方文档真的不好,很多东西太旧也不修改,写的很乱,这个问题就是由于使用了错误的传参导致的。

这个报错是canvas为空,可能有几个原因

  1. canvas没有被正确的初始化,没有设置宽度高度;
  2. canvas画布内容没有被绘制
  3. canvasToTempFilePath方法没有正确的调用

本文遇到的问题就是第三个原因,话不多说,附上代码:

  onReady() {
    const query = wx.createSelectorQuery();
    query
      .select("#signCanvas")
      .fields({ node: true, size: true, id: true })
      .exec((res) => {
        const canvas = res[0].node;
        if (!canvas) {
          console.error("Canvas not found");
          return;
        }

        this.canvasId = res[0].id; // 保存 canvasId
        this.ctx = canvas.getContext("2d");
        if (!this.ctx) {
          console.error("Failed to get canvas context");
          return;
        }

        const dpr = wx.getSystemInfoSync().pixelRatio;
        canvas.width = res[0].width * dpr;
        canvas.height = res[0].height * dpr;
        this.ctx.scale(dpr, dpr);

        console.log("Canvas initialized:", canvas);
        console.log("Canvas size:", canvas.width, canvas.height);
        console.log("Canvas ID:", this.canvasId);
        console.log("Canvas initialized, size:", canvas.width, "x", canvas.height);
      });
  },

  startDrawing(e) {
    const { x, y } = e.touches[0];
    this.setData({
      lastPoint: { x, y },
      isDrawing: true,
      hasDrawn: true, // 更新变量
    });
  },

  stopDrawing() {
    this.setData({
      isDrawing: false,
    });
  },

  moveDrawing(e) {
    if (!this.data.isDrawing) return;
    if (!this.ctx) {
      console.error("Canvas context is not initialized");
      return;
    }

    const { x, y } = e.touches[0];
    this.ctx.strokeStyle = this.data.color;
    this.ctx.lineWidth = this.data.thickness;
    this.ctx.lineJoin = "round";
    this.ctx.lineCap = "round";

    this.ctx.beginPath();
    this.ctx.moveTo(this.data.lastPoint.x, this.data.lastPoint.y);
    this.ctx.lineTo(x, y);
    this.ctx.stroke();

    this.setData({
      lastPoint: { x, y },
      hasDrawn: true,
    });
    console.log("Drawing at:", x, y, "with color", this.data.color, "and thickness", this.data.thickness);
  },

  clearCanvas() {
    const query = wx.createSelectorQuery();
    query
      .select("#signCanvas")
      .fields({ node: true, size: true })
      .exec((res) => {
        const canvas = res[0].node;
        if (!canvas) {
          console.error("Canvas not found");
          return;
        }

        const ctx = canvas.getContext("2d");
        if (!ctx) {
          console.error("Failed to get canvas context");
          return;
        }

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        this.setData({
          hasDrawn: false, // 清空画布后更新变量
        });

        console.log("Canvas cleared");
      });
  },

  saveSignature() {
    console.log("Attempting to save signature. Canvas ID:", this.canvasId, "Has Drawn:", this.data.hasDrawn);
    if (!this.data.hasDrawn) {
      wx.showToast({
        title: "画布为空",
        icon: "none",
        duration: 2000,
      });
      return;
    }

    const query = wx.createSelectorQuery();
    query.select("#" + this.canvasId)
        .fields({ node: true, size: true })
        .exec((res) => {
            const canvas = res[0].node;
            if (!canvas) {
              console.error("Canvas not found");
              return;
            }

            console.log("Saving canvas with ID:", this.canvasId);

            wx.canvasToTempFilePath({
              canvas: canvas,
              success: (res) => {
                wx.showToast({
                  title: "保存成功",
                  icon: "success",
                  duration: 2000,
                });
                console.log("File saved at:", res.tempFilePath);
              },
              fail: (err) => {
                wx.showToast({
                  title: "保存失败",
                  icon: "none",
                  duration: 2000,
                });
                console.error("Save failed:", err);
              },
            });
        });
},

这是全部代码,其中,wx.canvasToTempFilePath方法新版canvas 2d传参是一个对象,不是字符串,也不是canvasId,官方文档介绍如下图:

canvasToTempFilePath

canvasToTempFilePath

作为对比,我原来的代码如下:

saveSignature() {
    if (!this.data.hasDrawn) {
      wx.showToast({
        title: "画布为空",
        icon: "none",
        duration: 2000,
      });
      return;
    }

    console.log("Saving canvas with ID:", this.canvasId);

    wx.canvasToTempFilePath({
      canvasId: this.canvasId,
      success: (res) => {
        wx.showToast({
          title: "保存成功",
          icon: "success",
          duration: 2000,
        });
        console.log("File saved at:", res.tempFilePath);
        console.log("canvasId", this.canvasId);
      },
      fail: (err) => {
        wx.showToast({
          title: "保存失败",
          icon: "none",
          duration: 2000,
        });
        console.error("Save failed:", err);
      },
    });
  },

原来传参是这样的canvasId: this.canvasId,,其实不需要这个参数,需要的是canvas: canvas,

现在就可以正确保存了

总结

代码里面已经包含了全部的调试语句,根据控制台输出可以判断错误点,请自行判断。

微信小程序canvasToTempFilePath:fail fail canvas is empty

说明

如题,最近在写一个小程序时,canvas报错,canvasToTempFilePath:fail fail canvas is empty,记录一下如何修复

步骤

首先吐槽一句,微信小程序官方文档真的不好,很多东西太旧也不修改,写的很乱,这个问题就是由于使用了错误的传参导致的。

这个报错是canvas为空,可能有几个原因

  1. canvas没有被正确的初始化,没有设置宽度高度;
  2. canvas画布内容没有被绘制
  3. canvasToTempFilePath方法没有正确的调用

本文遇到的问题就是第三个原因,话不多说,附上代码:

  onReady() {
    const query = wx.createSelectorQuery();
    query
      .select("#signCanvas")
      .fields({ node: true, size: true, id: true })
      .exec((res) => {
        const canvas = res[0].node;
        if (!canvas) {
          console.error("Canvas not found");
          return;
        }

        this.canvasId = res[0].id; // 保存 canvasId
        this.ctx = canvas.getContext("2d");
        if (!this.ctx) {
          console.error("Failed to get canvas context");
          return;
        }

        const dpr = wx.getSystemInfoSync().pixelRatio;
        canvas.width = res[0].width * dpr;
        canvas.height = res[0].height * dpr;
        this.ctx.scale(dpr, dpr);

        console.log("Canvas initialized:", canvas);
        console.log("Canvas size:", canvas.width, canvas.height);
        console.log("Canvas ID:", this.canvasId);
        console.log("Canvas initialized, size:", canvas.width, "x", canvas.height);
      });
  },

  startDrawing(e) {
    const { x, y } = e.touches[0];
    this.setData({
      lastPoint: { x, y },
      isDrawing: true,
      hasDrawn: true, // 更新变量
    });
  },

  stopDrawing() {
    this.setData({
      isDrawing: false,
    });
  },

  moveDrawing(e) {
    if (!this.data.isDrawing) return;
    if (!this.ctx) {
      console.error("Canvas context is not initialized");
      return;
    }

    const { x, y } = e.touches[0];
    this.ctx.strokeStyle = this.data.color;
    this.ctx.lineWidth = this.data.thickness;
    this.ctx.lineJoin = "round";
    this.ctx.lineCap = "round";

    this.ctx.beginPath();
    this.ctx.moveTo(this.data.lastPoint.x, this.data.lastPoint.y);
    this.ctx.lineTo(x, y);
    this.ctx.stroke();

    this.setData({
      lastPoint: { x, y },
      hasDrawn: true,
    });
    console.log("Drawing at:", x, y, "with color", this.data.color, "and thickness", this.data.thickness);
  },

  clearCanvas() {
    const query = wx.createSelectorQuery();
    query
      .select("#signCanvas")
      .fields({ node: true, size: true })
      .exec((res) => {
        const canvas = res[0].node;
        if (!canvas) {
          console.error("Canvas not found");
          return;
        }

        const ctx = canvas.getContext("2d");
        if (!ctx) {
          console.error("Failed to get canvas context");
          return;
        }

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        this.setData({
          hasDrawn: false, // 清空画布后更新变量
        });

        console.log("Canvas cleared");
      });
  },

  saveSignature() {
    console.log("Attempting to save signature. Canvas ID:", this.canvasId, "Has Drawn:", this.data.hasDrawn);
    if (!this.data.hasDrawn) {
      wx.showToast({
        title: "画布为空",
        icon: "none",
        duration: 2000,
      });
      return;
    }

    const query = wx.createSelectorQuery();
    query.select("#" + this.canvasId)
        .fields({ node: true, size: true })
        .exec((res) => {
            const canvas = res[0].node;
            if (!canvas) {
              console.error("Canvas not found");
              return;
            }

            console.log("Saving canvas with ID:", this.canvasId);

            wx.canvasToTempFilePath({
              canvas: canvas,
              success: (res) => {
                wx.showToast({
                  title: "保存成功",
                  icon: "success",
                  duration: 2000,
                });
                console.log("File saved at:", res.tempFilePath);
              },
              fail: (err) => {
                wx.showToast({
                  title: "保存失败",
                  icon: "none",
                  duration: 2000,
                });
                console.error("Save failed:", err);
              },
            });
        });
},

这是全部代码,其中,wx.canvasToTempFilePath方法新版canvas 2d传参是一个对象,不是字符串,也不是canvasId,官方文档介绍如下图:

canvasToTempFilePath

canvasToTempFilePath

作为对比,我原来的代码如下:

saveSignature() {
    if (!this.data.hasDrawn) {
      wx.showToast({
        title: "画布为空",
        icon: "none",
        duration: 2000,
      });
      return;
    }

    console.log("Saving canvas with ID:", this.canvasId);

    wx.canvasToTempFilePath({
      canvasId: this.canvasId,
      success: (res) => {
        wx.showToast({
          title: "保存成功",
          icon: "success",
          duration: 2000,
        });
        console.log("File saved at:", res.tempFilePath);
        console.log("canvasId", this.canvasId);
      },
      fail: (err) => {
        wx.showToast({
          title: "保存失败",
          icon: "none",
          duration: 2000,
        });
        console.error("Save failed:", err);
      },
    });
  },

原来传参是这样的canvasId: this.canvasId,,其实不需要这个参数,需要的是canvas: canvas,

现在就可以正确保存了

总结

代码里面已经包含了全部的调试语句,根据控制台输出可以判断错误点,请自行判断。


赞 (0)

猜您想看

  • CentOS7下二进制安装Gitea配合宝塔面板实现反代

    最近因为个人原因,在频繁的写和更改代码,代码这种重要的东西,自然是需要多多备份的,但是,由于众所周知的原因,GitHub的上传和拉取速度实在感人,而无论是GitHub还是Gitee,都不能无限制私人仓库,所以准备自建Git,特此记录。

    2022年11月29日
  • 腾讯2021届秋招校园招聘前端笔试真题(第一次笔试)

    如题,本文内容为2021届秋招前端岗位第一次笔试真题。

    2020年10月23日
  • PotPlayer实时字幕翻译合集

    最近才发现PotPlayer自带字幕实时翻译功能,看一些没有翻译的视频的时候还是比较好用的,众所周知,由于一些国内的原因,PotPlayer内置的微软翻译、谷歌翻译等都不能很方便的使用,所以找了一下国内能用的翻译,特此记录。

    2020年11月21日
  • Android Studio报错error:connection timed out

    在构建Android项目的时候,底部的状态栏总是会显示connection timed out或Could not download xxx等问题,这是由于国内网络问题导致第三方依赖下载不上,特此记录其解决办法。

    2019年10月18日
  • 强力开源激活工具HEU_KMS_Activator

    本文记录开源程序HEU_KMS_Activator的使用方式

    2021年02月22日
  • 微信小程序使用fontawesome4.7图标方法

    最近在写了一个小程序,原生组件里面的图标很少,而且不好看,这里记录一下如何使用fontawesome4.7图标的方法。

    2023年07月18日

评论区(暂无评论)

这里空空如也,快来评论吧~

我要评论

Vaptcha 初始化中...