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

react-signature-canvas在Ant Design Modal中无法生成Base64图像问题

问题:React SignaturePad 嵌入 Ant Design Modal 无法生成有效 Base64 签名图像

将 SignaturePad 组件嵌入 Ant Design 的 Modal 组件中时,调用trim函数获取签名的 Base64 内容,返回值仅为"data:";移除 Modal 标签后,能正常返回完整的"data:image/png;base64,iVBORw0KGgoxxxxx...."格式内容,怀疑是签名库与 Ant Design Modal 的兼容问题。

相关代码

父组件 FormComponent

import { Form, Modal } from 'antd';

const FormComponent = () => {
  const [form] = Form.useForm();

  return (
      <Modal
        title="Signature Form"
        open={true}>
        <div>
          <Form
            form={form}
          >
            <div>
              <SignaturePad
                name="signature"
                title="Signature"
                setFieldValue={(fieldName, value) => {
                  formSign.setFieldsValue({ [fieldName]: value });
                }}
                status={undefined}
                skipValidation={false}
              />
            </div>
          </Form>
        </div>
      </Modal>
  );
};

自定义 SignaturePad 组件

import React, { useRef, RefObject } from 'react';
import SignaturePad from 'react-signature-canvas';
import { Button, Form } from 'antd';

interface SignaturePadProps {
  name: string;
  title: string;
  setFieldValue: (fieldName: string, value: any) => void;
  status?: 'error' | 'success';
  skipValidation?: boolean;
}

const SignaturePad: React.FC<SignaturePadProps> = ({
  name,
  title,
  setFieldValue,
  status,
  skipValidation,
}) => {
  const ref: RefObject<SignaturePad> = useRef<SignaturePad>(null);
  const isErrorBorder = status === 'error' ? 'signing-error-border' : '';

  const trim = () => {
    if (ref.current) {
      let sign = ref.current.toDataURL('image/png');
      setFieldValue(name, sign);
    }
  };

  const clear = () => {
    if (ref.current) {
      ref.current.clear();
      setFieldValue(name, '');
    }
  };

  return (
    <Form.Item
      {...{
        labelCol: {
          span: 4,
        }
      }}
      label={title}
      name={name}
      rules={[{ required: !skipValidation, message: 'This field is required' }]}
      valuePropName="data-url"
    >
      <section className='sign_form'>
        <SignaturePad
          onEnd={trim}
          canvasProps={{
            className: `sign_canvas ${isErrorBorder}`,
          }}
          ref={ref}
        />
        <Button onClick={clear} className='clear-btn'>
          Clear
        </Button>
      </section>
    </Form.Item>
  );
};

export default SignaturePad;

问题分析与解决方案

这不是直接的库兼容问题,核心原因是 Modal 初始化时,内部 Canvas 元素未完成尺寸渲染,导致toDataURL无法捕获有效画布内容。Ant Design Modal 默认是懒渲染机制,即使设置open={true},组件也会异步完成挂载,此时 Canvas 宽高可能为0,调用toDataURL就会返回空的data:字符串。

方案1:监听 Modal 渲染完成事件,延迟加载 SignaturePad

利用 Modal 的afterOpen回调,确保 Modal 完全渲染后再挂载 SignaturePad:

import { Form, Modal } from 'antd';
import { useState } from 'react';

const FormComponent = () => {
  const [form] = Form.useForm();
  const [modalReady, setModalReady] = useState(false);

  return (
      <Modal
        title="Signature Form"
        open={true}
        afterOpen={() => setModalReady(true)}>
        <div>
          <Form form={form}>
            {modalReady && (
              <div>
                <SignaturePad
                  name="signature"
                  title="Signature"
                  setFieldValue={(fieldName, value) => {
                    form.setFieldsValue({ [fieldName]: value });
                  }}
                  status={undefined}
                  skipValidation={false}
                />
              </div>
            )}
          </Form>
        </div>
      </Modal>
  );
};

方案2:为 Canvas 设置固定尺寸

在自定义 SignaturePad 组件中,给 Canvas 明确指定宽高,避免 Modal 渲染时尺寸异常:

<SignaturePad
  onEnd={trim}
  canvasProps={{
    className: `sign_canvas ${isErrorBorder}`,
    width: 500,
    height: 200
  }}
  ref={ref}
/>

方案3:在trim函数中检查并修正 Canvas 尺寸

在生成 Base64 前,确保 Canvas 有有效尺寸:

const trim = () => {
  if (ref.current) {
    const canvas = ref.current.getCanvas();
    // 若画布尺寸为0,设置默认值
    if (canvas.width === 0 || canvas.height === 0) {
      canvas.width = 500;
      canvas.height = 200;
    }
    let sign = ref.current.toDataURL('image/png');
    setFieldValue(name, sign);
  }
};

额外修正点

原父组件代码中formSign未定义,应改为form(方案1中已修正)。

内容的提问来源于stack exchange,提问作者Jing c

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 10:25:55