微信小程序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)

猜您想看

  • 关于京东京造和耐时干电池的使用体验

    由于平时键盘和鼠标以及Xbox手柄用的都是干电池,所以也关注了市面上的很多电池,下面就记录一下使用情况,供大家参考。

    2024年04月28日
  • 三星(SAMSUNG)970 EVO Plus使用体验

    如题,前一阵子在狗东三星自营420购入一块三星(SAMSUNG)250GB SSD固态硬盘 M.2接口(NVMe协议) 970 EVO Plus,与之前买的西数128G SATA固态一起服役。

    2020年01月16日
  • AMD R5 5600G装机体验

    这两天给家里装了一台电脑,平时家人办公用的,配置不需要很高,记录一下

    2023年05月03日
  • 微信每日定时发送问候dailyGreeting

    每天给女友发送早安晚安比较繁琐,而且也容易忘记,利用微信公众号可以定时发送模板消息,设定内容,十分方便,特此记录。

    2022年11月03日
  • elementUI选择框实现全选功能

    如题,前两天写一个功能的时候需要用到选择框的多选功能,记录一下

    2023年04月29日
  • AWS亚马逊云入坑记录

    作为云服务的老大,想来品质应该是可以的,听说有一年的免费主机,所以试试。

    2019年02月07日

评论区(暂无评论)

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

我要评论

Vaptcha 初始化中...