react-svg-pan-zoom vs react-zoom-pan-pinch
React 中的图像与 SVG 交互:平移、缩放和捏合手势对比
react-svg-pan-zoomreact-zoom-pan-pinch类似的npm包:

React 中的图像与 SVG 交互:平移、缩放和捏合手势对比

react-svg-pan-zoomreact-zoom-pan-pinch 都是用于在 React 应用中实现图像或 SVG 内容平移、缩放和捏合手势的库,但它们的适用场景和底层实现有显著区别。

react-svg-pan-zoom 专为 SVG 元素设计,它直接操作 SVG 的 viewBox 属性来实现缩放和平移。这意味着它非常适合处理矢量图形、图表或需要保持无限清晰度的场景。它不依赖外部库,轻量且对 SVG 结构有深度控制。

react-zoom-pan-pinch 则是一个更通用的解决方案,适用于任何 DOM 元素(如 <img>, <div>, <canvas>)。它通过 CSS transform (translate, scale) 来移动和缩放内容容器。它内置了丰富的触摸手势支持(捏合、双击、拖拽),并提供了大量的配置项来控制动画、限制边界和自定义行为,是处理位图或复杂 DOM 结构的理想选择。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
react-svg-pan-zoom06961.02 MB412 年前MIT
react-zoom-pan-pinch01,9231.2 MB1916 天前MIT

React SVG 与通用图像交互方案深度对比:react-svg-pan-zoom vs react-zoom-pan-pinch

在 React 生态中处理可交互的视觉内容(如地图、图表、大图查看器)时,开发者常面临一个选择:是使用专为 SVG 设计的工具,还是选择通用的 DOM 变换库?react-svg-pan-zoomreact-zoom-pan-pinch 分别代表了这两种技术路线。虽然它们的目标相似——让用户能够平移和缩放内容,但它们的底层原理、适用场景和 API 设计哲学截然不同。

🧬 核心原理:SVG viewBox 变换 vs CSS Transform

这是两者最根本的区别,直接决定了它们的性能表现和适用场景。

react-svg-pan-zoom 的工作原理是直接修改 SVG 元素的 viewBox 属性。

  • 它不改变 DOM 结构,也不使用 CSS transform
  • 缩放本质上是改变 SVG 的可视区域坐标。
  • 优势:矢量图形在任何缩放级别下都绝对清晰,没有像素化问题;坐标计算基于 SVG 原生坐标系,非常适合数据可视化。
  • 局限:仅支持 SVG 元素,无法处理 <img> 标签或普通 div
// react-svg-pan-zoom: 直接操作 SVG viewBox
import ReactSVGPanZoom from 'react-svg-pan-zoom';

function SvgViewer() {
  return (
    <ReactSVGPanZoom
      width={500}
      height={500}
      tool="auto"
      SVGBackground="white"
    >
      <svg>
        <rect x="10" y="10" width="100" height="100" fill="blue" />
        <circle cx="150" cy="150" r="50" fill="red" />
      </svg>
    </ReactSVGPanZoom>
  );
}

react-zoom-pan-pinch 则是通过包裹一个 div 容器,并对其子元素应用 CSS transform: translate(...) scale(...) 来实现效果。

  • 它适用于任何 DOM 元素(图片、Canvas、HTML 文本等)。
  • 缩放是通过浏览器的合成层(Compositor)进行的,性能通常很好,但在极高倍数缩放位图时会出现像素化。
  • 优势:通用性强,支持丰富的手势(捏合、双击、拖拽),配置灵活。
  • 局限:处理超大图片时需注意内存,且位图缩放有清晰度上限。
// react-zoom-pan-pinch: 使用 CSS Transform 包裹任意内容
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';

function ImageViewer() {
  return (
    <TransformWrapper
      initialScale={1}
      limitToBounds={true}
      centerOnInit={true}
    >
      <TransformComponent>
        <img src="/large-image.jpg" alt="Zoomable content" style={{ width: '100%' }} />
        {/* 也可以是复杂的 DOM 结构 */}
        <div style={{ position: 'absolute', top: 50, left: 50 }}>Overlay Text</div>
      </TransformComponent>
    </TransformWrapper>
  );
}

🖐️ 交互体验与手势支持

对于现代 Web 应用,尤其是移动端,手势支持的丰富程度直接影响用户体验。

react-svg-pan-zoom 提供了基础的交互能力。

  • 支持鼠标拖拽平移、滚轮缩放。
  • 支持简单的点击和双击重置。
  • 缺失:原生不支持多指捏合手势(Pinch-to-zoom)。在移动设备上,用户无法通过双指捏合来缩放 SVG,这通常需要通过额外的桥接代码或浏览器默认行为来实现,体验不够流畅。
// react-svg-pan-zoom: 基础工具配置
<ReactSVGPanZoom
  tool="pan" // 可选 'pan', 'box', 'auto'
  onZoom={ (value) => console.log('Zoom level:', value) }
  // 没有内置的 onPinch 回调
/>

react-zoom-pan-pinch 则是为触摸交互而生的。

  • 内置完整的多指捏合缩放支持。
  • 支持双击放大/缩小(可配置点击位置)。
  • 支持惯性滑动(Momentum),让拖拽感觉更自然。
  • 提供详细的事件回调,允许开发者拦截或增强手势行为。
// react-zoom-pan-pinch: 丰富的手势配置
<TransformWrapper
  onPinchStart={({ state }) => console.log('Pinch started')}
  onPinch={({ state }) => console.log('Pinching...', state.scale)}
  onPinchStop={({ state }) => console.log('Pinch ended')}
  doubleClick={{ mode: 'zoomIn' }} // 双击模式
  velocityAnimation={{ enabled: true }} // 开启惯性动画
>
  <TransformComponent>
    <img src="/map.png" alt="Map" />
  </TransformComponent>
</TransformWrapper>

🎛️ 控制与 API 灵活性

在复杂应用中,程序化控制(通过代码触发缩放/平移)至关重要。

react-svg-pan-zoom 的控制相对直接,主要通过 ref 调用实例方法。

  • API 较为底层,侧重于 SVG 特定的操作(如 fitToViewer, zoomOnViewerCenter)。
  • 状态管理相对简单,但定制动画曲线较难。
// react-svg-pan-zoom: 通过 Ref 控制
const viewerRef = useRef(null);

const handleFit = () => {
  if (viewerRef.current) {
    viewerRef.current.fitToViewer(); // 适应视图
  }
};

const handleZoomIn = () => {
  if (viewerRef.current) {
    viewerRef.current.zoomOnViewerCenter(1.2); // 中心放大
  }
};

<ReactSVGPanZoom ref={viewerRef} ... />

react-zoom-pan-pinch 提供了极其丰富的控制选项和钩子。

  • 除了 ref 方法外,还暴露了 context 对象,可以在组件内部访问状态。
  • 支持自定义动画缓动函数、缩放步长、边界检测逻辑。
  • 可以轻松实现“点击某点放大”、“限制最大缩放倍数”等复杂逻辑。
// react-zoom-pan-pinch: 高级控制与 Ref
const { zoomIn, zoomOut, centerView, setTransform } = useRef(null);

const handleCustomZoom = () => {
  // 程序化设置特定的变换矩阵
  setTransform(100, 100, 2.5, 1000); // x, y, scale, animationTime
};

<TransformWrapper
  ref={useRef}
  minScale={0.5}
  maxScale={10}
  wheel={{ step: 0.1 }} // 自定义滚轮步长
>
  <TransformComponent>
    <button onClick={handleCustomZoom}>Go to Specific View</button>
    <img src="/diagram.png" alt="Diagram" />
  </TransformComponent>
</TransformWrapper>

📐 边界处理与布局适应

如何处理内容超出容器边界,是这两个库另一个重要的分水岭。

react-svg-pan-zoom 依赖于 SVG 的 viewBox 逻辑。

  • 它可以设置 disablePandisableZoom 来限制行为。
  • 对于“限制在容器内”的需求,它表现良好,但对于非矩形内容或复杂边界,控制力有限。
  • 它的布局完全由 SVG 的 width/heightviewBox 决定,有时在响应式布局中需要额外计算。
// react-svg-pan-zoom: 基础限制
<ReactSVGPanZoom
  disablePan={false}
  disableZoom={false}
  // 没有内置的复杂的边界碰撞检测配置
  detectAutoPan={true} 
/>

react-zoom-pan-pinch 拥有强大的边界检测系统。

  • limitToBounds 属性可以强制内容不超出容器范围。
  • alignmentAnimation 可以在用户释放鼠标后,自动将内容对齐到边界。
  • 支持自定义 bounds 计算逻辑,适应不规则布局。
// react-zoom-pan-pinch: 强大的边界控制
<TransformWrapper
  limitToBounds={true} // 关键:限制在边界内
  centerOnInit={true}
  alignmentAnimation={{ disabled: false }} // 自动回弹对齐
  padding={{ size: 10 }} // 设置内边距,允许稍微超出
>
  <TransformComponent>
    <img src="/photo.jpg" alt="Bounded Photo" />
  </TransformComponent>
</TransformWrapper>

🌐 相似之处:共同的目标

尽管实现路径不同,这两个库在解决核心问题上有着共同的立场:

1. 🔄 状态驱动与 React 集成

  • 两者都设计为受控或非受控组件,能够很好地融入 React 的生命周期。
  • 都支持通过 onChange 或类似回调同步状态到外部 Store(如 Redux/Zustand)。
// 两者都支持状态同步
// react-svg-pan-zoom
<ReactSVGPanZoom onChangeValue={(value) => saveToStore(value)} />

// react-zoom-pan-pinch
<TransformWrapper onZoom={({ state }) => saveToStore(state)} />

2. 🛠️ 基础工具集

  • 都提供了平移(Pan)、缩放(Zoom)、重置(Reset)的核心功能。
  • 都支持键盘快捷键的扩展(虽然需要少量自定义代码)。
// 都可以实现重置功能
// react-svg-pan-zoom
viewerRef.current.reset();

// react-zoom-pan-pinch
zoomIn(); // 或通过 ref.resetTransform()

3. 📱 响应式支持

  • 两者都能适应容器大小的变化(尽管 react-zoom-pan-pinch 在处理动态尺寸变化时通常更顺滑,因为它基于 DOM 布局)。

📊 总结对比表

特性react-svg-pan-zoomreact-zoom-pan-pinch
核心对象仅限 <svg> 元素任意 DOM 元素 (img, div, canvas)
变换原理修改 SVG viewBoxCSS transform (translate/scale)
图像质量无限清晰 (矢量)依赖源图分辨率 (位图可能模糊)
触摸手势基础 (拖拽/滚轮),无原生捏合完整支持 (捏合/双击/惯性)
配置复杂度低,API 简单直接高,提供大量细粒度配置项
边界控制基础高级 (自动回弹/限制/内边距)
典型场景流程图、架构图、数据图表地图应用、图片查看器、细节检查工具

💡 架构决策建议

选择 react-svg-pan-zoom 的理由: 如果你的应用场景是技术绘图、流程图编辑器或数据可视化仪表盘,且内容完全是 SVG 格式,那么这个库是更纯粹的选择。它没有多余的 DOM 嵌套,直接操作 SVG 核心属性,能保证矢量图形的完美渲染。但你要做好在移动端自行处理捏合手势的心理准备,或者接受移动端体验稍弱的事实。

选择 react-zoom-pan-pinch 的理由: 如果你正在构建**图片浏览器、在线地图、或者需要混合渲染(图片 + HTML 标注)**的应用,react-zoom-pan-pinch 是不二之选。它对触摸设备的原生支持极佳,配置项丰富到几乎可以模拟任何现有的商业地图或照片应用的行为。虽然它在处理超大 SVG 时可能不如前者轻量,但其通用性和交互流畅度在大多数 C 端产品中更具优势。

最终建议:不要试图用 react-svg-pan-zoom 去做图片查看器,也不要用 react-zoom-pan-pinch 去处理需要极高精度坐标计算的矢量编辑工具。让工具回归其最擅长的领域,是保持前端架构清晰的关键。

如何选择: react-svg-pan-zoom vs react-zoom-pan-pinch

  • react-svg-pan-zoom:

    如果你的核心需求是处理 SVG 矢量图形(如流程图、地图、数据可视化图表),请选择 react-svg-pan-zoom。它直接修改 SVG 的 viewBox,确保在任何缩放级别下图形都保持锐利,且不会像 CSS 变换那样可能导致子元素渲染模糊。它适合需要精确控制 SVG 内部坐标系统,且不需要复杂触摸手势(如双指旋转)的场景。

  • react-zoom-pan-pinch:

    如果你需要处理 位图图像 (<img>)复杂的 DOM 结构 或者需要 高级触摸手势(如双指捏合缩放、双击放大、惯性滑动),请选择 react-zoom-pan-pinch。它的 API 设计更加灵活,支持任意 DOM 节点作为容器,并提供了丰富的配置项来定制边界限制、动画效果和手势行为。它是构建类似谷歌地图或照片查看器体验的首选方案。

react-svg-pan-zoom的README

react-svg-pan-zoom

react-svg-pan-zoom is a React component that adds pan and zoom features to the SVG images. It helps to display big SVG images in a small space.

chrvadala Test npm Downloads Donate

react-svg-pan-zoom

Live Demo

available at http://chrvadala.github.io/react-svg-pan-zoom/

Features

This component can work in four different modes depending on the selected tool:

  • With the tool pan the user can move the image and drag it around within the viewer, but can't interact with SVG child elements.
  • With the tool zoom the user can scale the image either with a point click or selecting a region to zoom the specified area, but can't interact with SVG child elements.
  • With the tool none the user can interact with SVG child elements and trigger events.
  • With the tool auto the user can interact with SVG child elements, perform pan (dragging the image), zoom in (double click), zoom out (double click + shift).

Documentation

Install

NPM

npm install --save react-svg-pan-zoom

YARN

yarn add react-svg-pan-zoom

UMD

<script src="https://unpkg.com/prop-types@15/prop-types.js"></script>
<script src="https://unpkg.com/react-svg-pan-zoom@3"></script>

Usage examples

Changelog

  • v2.0 - Project refactor. Follow this guide for migration instructions.
  • v2.1 - Adds setPointOnViewerCenter, reset methods and className, style props
  • v2.2 - Introduces tool auto, improves default toolbar
  • v2.3 - Adds touch events support
  • v2.4 - Adds es:next support, deploy new website
  • v2.5 - Adds preventPanOutside and scaleFactor props
  • v2.6 - Introduces transformation-matrix that reduces bundle size thanks to three shaking, Fixes pan limit behaviour, Replaces toolbar links with buttons, minor improvements
  • v2.7 - Adds miniature feature, Adds PropTypes support
  • v2.8 - Adds storybook demo, Remove bower support, Adds pinch to zoom feature, Fixes miniature size
  • v2.9 - Reinvents miniature and introduce props miniatureBackground, miniatureHeight, Minor improvements & fix
  • v2.10 - Introduces prop disableDoubleClickZoomWithToolAuto
  • v2.11 - Improves docs, updates deps
  • v2.12 - Exports miniature to allow customization
  • v2.13 - Fixes resize issues (#58), Upgrades deps
  • v2.14 - Introduces prop scaleFactorOnWheel, Upgrades deps
  • v2.15 - Improves autopan feature (#71), adds scaleFactorMax, scaleFactorMin props (#71), Upgrades deps
  • v2.16 - Adds onPan and onZoom callbacks, Upgrade deps, Fixes boundaries feature
  • v2.17 - Upgrades deps
  • v2.18 - Introduces toolbarProps.SVGAlignX and toolbarProps.SVGAlignY props. Adds alignment configuration in fitToViewer(SVGAlignX = "left", SVGAlignY = "top") method (#120). Upgrades deps.
  • v3.0 - Upgrades to babel 7 and storybook 4; Introduces <UncontrolledReactSVGPanZoom /> component and makes <ReactSVGPanZoom> a stateless component (except for some optimizations); Moves props related to miniature and toolbar, respectively into the miniatureProp and toolbarProp props. Migration guide is available here.
  • v3.1 - Upgrades to storybook 5 and transformation-matrix 2; Fixes some Babel configuration issues
  • v3.2 - Upgrades deps
  • v3.3 - Adds SVG viewbox prop support #150
  • v3.4 - Upgrades deps and increases code quality (fixing eslint warnings)
  • v3.5 - Handles wheel event as passive #158, upgrades deps
  • v3.6 - Adds some unit tests, Fixes #161, upgrades deps
  • v3.7 - Adds some more unit tests, upgrades deps
  • v3.8 - Adds cover option on fitToViewer method #167, adds activeToolColor property #168, upgrades deps
  • v3.9 - Exports toolbar icons and buttons #192
  • 3.10 - Upgrades deps; Migrates to React 17 and Storybook 6; Updates examples and docs to React hooks
  • 3.11 - Migrates from yarn to npm; Makes use of chrvadala/github-actions; Updates deps;
  • 3.12 - Migrates to gh-sponsor; Improves docs; Deprecates v1 migration guide; Upgrades deps;
  • 3.13 - Fixes migration doc #218; Removes deprecated defaultProps; Migrates to Storybook 8; Upgrades deps; Upgrades gh-actions;

Some projects using react-svg-pan-zoom

Contributors