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

React PDF缩放时,Viewport Scale是否需与Page Scale同步?

问题

我在React项目中使用封装了pdf.js的react-pdf组件展示PDF文件,目前通过如下代码设置scale实现PDF的放大与缩小:

<Page
  key={index + "@new-" + projAttribute.pdfScale}
  scale={projAttribute.pdfScale}
  className={styles.pdfPage}
  onLoad={handlePageChange}
  canvasRef={(element) => updateRefArray(index, element)}
  onChange={handlePageChange}
  onRenderSuccess={handlePageRenderSuccess}
  pageNumber={index}
  width={width}
>
  {curPdfPosition && viewPort ? (
    <Highlight
      position={curPdfPosition}
      pageNumber={index}
      viewport={viewPort}
    ></Highlight>
  ) : (
    <div></div>
  )}
</Page>

同时通过以下代码获取viewport:

React.useEffect(() => {
  setPageViewports(undefined);

  if (!pdf) {
    return;
  }

  (async () => {
    const pageNumbers = Array.from(new Array(pdf.numPages)).map(
      (_, index) => index + 1
    );

    const nextPageViewports = await asyncMap(
      pageNumbers,
      (pageNumber: number) =>
        pdf
          .getPage(pageNumber)
          .then((page) =>
            page.getViewport({ scale: projAttr.pdfScale || 1 })
          )
    );
    setPageViewports(nextPageViewports);
  })();
}, [pdf]);

我的PDF缩放范围为0.1-6.0,每次点击缩放按钮增减0.1。请问在此场景下,是否需要同步修改viewport的scale,使其与PDF的scale保持一致?或者viewport的scale应设置为其他值?

回答

必须同步修改viewport的scale,让它和<Page>组件的scale值保持一致,核心原因如下:

  • 高亮定位精准性:你使用的<Highlight>组件依赖viewport来计算高亮区域的像素坐标。如果viewport的scale与PDF显示的scale不匹配,高亮会出现偏移,无法准确对应到PDF页面上的目标位置。
  • 坐标映射一致性:pdf.js的viewport负责将PDF原生的72DPI坐标转换为页面显示的像素坐标。只有当viewport的scale和<Page>的scale完全一致时,所有基于坐标的操作(比如高亮、批注、点击定位)才能和视觉显示完全匹配。
  • 当前代码的缺陷:你的useEffect仅监听pdf的变化,未监听projAttr.pdfScale。这意味着用户点击缩放按钮修改pdfScale时,viewport不会更新,会直接导致后续高亮等操作失效或错位。

修正方案

将projAttr.pdfScale加入useEffect的依赖数组,确保每次缩放值变化时,重新计算对应scale的viewport:

React.useEffect(() => {
  setPageViewports(undefined);

  if (!pdf) {
    return;
  }

  (async () => {
    const pageNumbers = Array.from(new Array(pdf.numPages)).map(
      (_, index) => index + 1
    );

    const nextPageViewports = await asyncMap(
      pageNumbers,
      (pageNumber: number) =>
        pdf
          .getPage(pageNumber)
          .then((page) =>
            page.getViewport({ scale: projAttr.pdfScale || 1 })
          )
    );
    setPageViewports(nextPageViewports);
  })();
}, [pdf, projAttr.pdfScale]); // 新增pdfScale到依赖列表

另外,建议在<Page>的onRenderSuccess回调中也获取当前页面的viewport,作为兜底方案,避免异步加载导致的viewport与显示scale不同步问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:05:17