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

如何将DocuSign集成到React应用并实现PDF签名区域拖拽定位功能?

React 实现PDF拖拽签名区域并捕获坐标方案

我之前做过类似需求,核心思路是用react-pdf渲染PDF,结合拖拽库(或原生拖拽事件)实现签名区域的位置调整,最后将页面像素坐标转换为PDF原生坐标并记录页码。以下是完整可落地的方案:

核心依赖

先安装必要依赖:

npm install react-pdf react-dnd react-dnd-html5-backend

完整代码实现

1. 可拖拽签名区域组件

import { useDrag } from 'react-dnd';

const SignatureArea = ({ onPositionChange, pageNumber }) => {
  const [{ isDragging }, dragRef] = useDrag({
    type: 'SIGNATURE',
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
    end: (_, monitor) => {
      const dropResult = monitor.getDropResult();
      if (!dropResult?.pageRef) return;

      // 获取PDF页面的渲染区域信息
      const pageElement = dropResult.pageRef.current;
      const pageRect = pageElement.getBoundingClientRect();
      const mousePos = monitor.getClientOffset();

      // 转换为PDF原生坐标(PDF默认72DPI,宽度612px)
      const pdfOriginalWidth = 612;
      const scaleRatio = pdfOriginalWidth / pageRect.width;
      
      const finalPos = {
        x: Math.round((mousePos.x - pageRect.left) * scaleRatio),
        y: Math.round((mousePos.y - pageRect.top) * scaleRatio),
        page: pageNumber
      };

      onPositionChange(finalPos);
    },
  });

  return (
    <div
      ref={dragRef}
      style={{
        position: 'absolute',
        width: '100px',
        height: '50px',
        border: '2px dashed #2196F3',
        backgroundColor: isDragging ? 'rgba(33,150,243,0.2)' : 'transparent',
        cursor: 'move',
        top: '20px',
        left: '20px'
      }}
    />
  );
};

2. PDF页面拖拽容器

import { useRef } from 'react';
import { Page } from 'react-pdf';
import { useDrop } from 'react-dnd';

const PDFPageContainer = ({ pageNumber, onSignatureDrop, children }) => {
  const pageRef = useRef(null);
  const [{ isOver }, dropRef] = useDrop({
    accept: 'SIGNATURE',
    collect: (monitor) => ({
      isOver: monitor.isOver(),
    }),
    drop: () => ({ pageRef })
  });

  return (
    <div
      ref={dropRef}
      style={{
        position: 'relative',
        margin: '20px auto',
        maxWidth: '800px',
        border: isOver ? '2px solid #4CAF50' : 'none'
      }}
    >
      <Page
        ref={pageRef}
        pageNumber={pageNumber}
        renderTextLayer={false}
        renderAnnotationLayer={false}
        width={800}
      />
      {children}
    </div>
  );
};

3. 主应用组件

import { useState } from 'react';
import { Document } from 'react-pdf';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import PDFPageContainer from './PDFPageContainer';
import SignatureArea from './SignatureArea';

const PDFSignatureApp = () => {
  const [pdfUrl, setPdfUrl] = useState(null);
  const [totalPages, setTotalPages] = useState(0);
  const [signaturePos, setSignaturePos] = useState(null);

  const handleFileUpload = (e) => {
    const file = e.target.files[0];
    if (file) setPdfUrl(URL.createObjectURL(file));
  };

  const handleDocLoad = ({ numPages }) => setTotalPages(numPages);

  return (
    <div style={{ padding: '20px' }}>
      <input type="file" accept=".pdf" onChange={handleFileUpload} />
      
      {pdfUrl && (
        <DndProvider backend={HTML5Backend}>
          <Document file={pdfUrl} onLoadSuccess={handleDocLoad}>
            {Array.from({ length: totalPages }, (_, idx) => (
              <PDFPageContainer key={idx + 1} pageNumber={idx + 1}>
                <SignatureArea 
                  pageNumber={idx + 1} 
                  onPositionChange={setSignaturePos} 
                />
              </PDFPageContainer>
            ))}
          </Document>
        </DndProvider>
      )}

      {signaturePos && (
        <div style={{ marginTop: '20px', padding: '10px', backgroundColor: '#f5f5f5' }}>
          <h4>签名区域坐标:</h4>
          <pre>{JSON.stringify(signaturePos, null, 2)}</pre>
        </div>
      )}
    </div>
  );
};

export default PDFSignatureApp;

关键注意事项

  • 坐标转换逻辑:PDF默认采用72DPI的坐标系统,宽度为612px(8.5英寸),如果你的PDF是自定义尺寸,需要通过Page组件的onLoadSuccess事件获取页面原始尺寸,替换代码中的pdfOriginalWidth。
  • 多签名支持:如果需要添加多个签名区域,只需将signaturePos改为数组类型,在onPositionChange中追加坐标对象即可。
  • 原生拖拽替代:如果不想用react-dnd,可以通过原生的dragstart、dragover、drop事件实现,核心逻辑都是在拖拽结束时计算相对页面的坐标并转换为PDF原生坐标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:13:15