You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中Canvas转Blob加入FormData首次报错二次正常问题求助

解决Canvas转Blob首次提交无效问题

问题根源在于图片加载是异步操作,首次提交时ticket图片还没加载完成就执行了drawImage和后续的toBlob,导致Canvas内容不完整,最终dataBlob可能为null,不符合FormData.append对Blob类型的要求。二次提交时图片已被浏览器缓存,加载瞬间完成,所以能正常生成Blob。

保留现有canvas.toBlob逻辑的前提下,只需确保图片加载完成后再执行Canvas绘制操作,修改后的代码如下:

<Formik
  validationSchema={schema}
  onSubmit={async (values) => {
    try {
      // 创建Canvas并等待图片加载完成
      const canvas = document.createElement("canvas");
      const layout = canvas.getContext("2d");
      const ticket = new Image();
      // 用Promise包裹图片加载,确保加载完成后再执行后续逻辑
      await new Promise((resolve, reject) => {
        ticket.onload = resolve;
        ticket.onerror = reject;
        ticket.src = target.ticket_img;
      });

      // 图片加载完成后设置Canvas尺寸并绘制图片
      canvas.width = ticket.naturalWidth;
      canvas.height = ticket.naturalHeight;
      layout.drawImage(
        ticket,
        0,
        0,
        ticket.naturalWidth,
        ticket.naturalHeight
      );

      // 添加宾客姓名文字
      const textName = values.name;
      layout.rotate(4.71);
      layout.font = "52px Archive";
      layout.fillStyle = "#faf9f6";
      layout.textAlign = "center";
      layout.strokeText(textName, -255, 1170);
      layout.fillText(textName, -255, 1170);

      layout.font = "52px Archive";
      layout.fillStyle = "#faf9f6";
      const textSurname = values.surname;
      layout.textAlign = "center";
      layout.strokeText(textSurname, -255, 1230);
      layout.fillText(textSurname, -255, 1230);

      // 转为Blob
      const dataBlob = await new Promise((resolve) =>
        canvas.toBlob((blob) => resolve(blob), "image/webp")
      );

      // 构建FormData并提交
      const formData = new FormData();
      formData.append(
        "image",
        dataBlob,
        `${target.title}_${values.name}${values.surname}_GUEST`
      );

      // 后续提交逻辑...
    } catch (err) {
      console.log(err);
    }
  }}
>
  {/* 表单内容 */}
</Formik>

关键改动说明:

  • 新增await new Promise包裹图片加载过程,通过ticket.onload确保图片加载完成后才继续执行
  • 将原有的图片绘制、文字添加等逻辑移到图片加载完成的回调之后,保证Canvas能正确渲染完整内容

这样修改后,无论首次还是后续提交,都会等待图片加载完成后再生成Blob,避免因图片未加载导致的dataBlob无效问题。

内容的提问来源于stack exchange,提问作者Vladislav Marinov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:53:13