react-easy-panzoom
Version:
Wrapper to enable pan and zoom for any React component
182 lines (149 loc) • 7.02 kB
Markdown
[](https://github.com/mnogueron/react-easy-panzoom)
[](https://github.com/mnogueron/react-easy-panzoom)
[](https://www.npmjs.com/package/react-easy-panzoom)
[](https://www.npmjs.com/package/react-easy-panzoom)
[](https://travis-ci.com/mnogueron/react-easy-panzoom)

React components that enables pan and zoom features for any component. Try out the live demo __[here](https://codesandbox.io/s/ll1xrz9mx9)__
react-panzoom requires React 16 or later.
Using `npm`:
```shell
npm install --save react-easy-panzoom
```
Using `yarn`:
```shell
yarn add react-easy-panzoom
```
```js
import { PanZoom } from 'react-easy-panzoom'
// ...
render() {
return (
<PanZoom>
{ 'This content can be panned and zoomed' }
</PanZoom>
)
}
```
`PanZoom` component natively supports keyboard interactions with arrow keys and `-` / `+` keys. This mapping can be extends using the `keyMapping` prop.
e.g. Mapping `w`, `a`, `s`, `d`:
```js
import { PanZoom } from 'react-easy-panzoom'
// ...
render() {
return (
<PanZoom
keyMapping={{
'87': { x: 0, y: -1, z: 0 },
'83': { x: 0, y: 1, z: 0 },
'65': { x: -1, y: 0, z: 0 },
'68': { x: 1, y: 0, z: 0 },
}}
>
{ 'This content can be panned and zoomed' }
</PanZoom>
)
}
```
Sometimes it can be useful to prevent the view from panning, for example if the pan start is done on a clickable element.
`PanZoom` provides the `preventPan` prop that let you define a function to prevent panning.
e.g. prevent panning when starting the pan on a specific `div`
```js
content = null
// preventPan gives access to the event, as well as the
// mouse coordinates in the coordinate system of the PanZoom container
preventPan = (event, x, y) => {
// if the target is the content container then prevent panning
if (e.target === content) {
return true
}
// in the case the target is not the content container
// use the coordinates to determine if the click happened
// on the content container
const contentRect = content.getBoundingClientRect()
const x1 = contentRect.left
const x2 = contentRect.right
const y1 = contentRect.top
const y2 = contentRect.bottom
return (x >= x1 && x <= x2) && (y >= y1 && y <= y2)
}
render() {
return (
<PanZoom
preventPan={this.preventPan}
>
<div>{ 'This content can be panned and zoomed' }</div>
<div ref={ref => this.content = ref}>{ 'This content can be panned and zoomed only outside of its container' }</div>
</PanZoom>
)
}
```
`PanZoom` supports the `enableBoundingBox` prop to restrict panning. The box is calculated based on the width and height of the inner content.
A ratio is applied so that the bounding box allows panning up to a specific percentage of the inner content.
By default this ratio is `0.8` but can be modified with `boundaryRatioVertical` and `boundaryRatioHorizontal`. In this case the pan content will be able to pan outside the parent container up to 80% of its size (the 20% remaining will always be visible).
A negative ratio will create a padding, but combined with zooming it can produce strange behaviour.
A ratio above 1 will allow the pan content to pan outside the parent container more than its size.
To use the bounding box:
```js
import { PanZoom } from 'react-easy-panzoom'
// ...
render() {
return (
<PanZoom
boundaryRatioVertical={0.8}
boundaryRatioHorizontal={0.8}
enableBoundingBox
>
<div>{ 'This content can be panned and zoomed' }</div>
</PanZoom>
)
}
```
|Name|Type|Default|Description|
|---|---|---|---|
|autoCenter|`bool`|false|Auto-center the view when mounting|
|autoCenterZoomLevel|`number`| |Specify the initial zoom level for auto-center|
|zoomSpeed|`number`|1|Sets the zoom speed|
|doubleZoomSpeed|`number`|1.75|Sets the zoom speed for double click|
|disabled|`bool`|false|Disable pan and zoom|
|disableKeyInteraction|`bool`|false|Disable keyboard interaction|
|disableDoubleClickZoom|`bool`|false|Disable zoom when performing a double click|
|disableScrollZoom|`bool`|false|Disable zoom when performing a scroll|
|realPinch|`bool`|false|Enable real pinch interaction for touch events|
|keyMapping|`object`|false|Define specific key mapping for keyboard interaction (e.g. `{ '<keyCode>': { x: 0, y: 1, z: 0 } }`, with `<keyCode>` being the key code to map)|
|minZoom|`number`| |Sets the minimum zoom value|
|maxZoom|`number`| |Sets the maximum zoom value|
|enableBoundingBox|`boolean`|false|Enable bounding box for the panzoom element. The bounding box will contain the element based on a ratio of its size|
|boundaryRatioVertical|`number`|0.8|Vertical ratio for the bounding box|
|boundaryRatioHorizontal|`number`|0.8|Horizontal ratio for the bounding box|
|noStateUpdate|`bool`|true|Disable state update for each new x, y, z transform value while panning. Enabling it drastically increases the performances |
|onPanStart|`func`| |Fired on pan start|
|onPan|`func`| |Fired on pan|
|onPanEnd|`func`| |Fired on pan end|
|preventPan|`func`| |Defines a function to prevent pan|
|style|`object`| |Override the inline-styles of the root element|
|onStateChange|`func`| |Called after the state of the component has changed|
You can also pass in every other props you would pass to a `div` element. Those will be passed through to the container component. This is helpful for adding custom event handlers.
## Methods
By using `ref`, methods from `PanZoom` can be accessed and called to trigger manipulation functions.
Available methods are listed below:
|Name|Parameters|Description|
|---|---|---|
|zoomIn|`(zoomSpeed?: number)`|Zoom in from the center of the `PanZoom` container|
|zoomOut|`(zoomSpeed?: number)`|Zoom out from the center of the `PanZoom` container|
|autoCenter|`(zoom: number, animate?: boolean = true)`|Center and resize the view to fit the `PanZoom` container|
|reset| |Reset the view to it's original state (will not auto center if `autoCenter` is enabled)|
|moveByRatio|`(x: number, y: number, moveSpeedRatio?: number)`|Move the view along `x` or/and `y` axis|
|rotate|`(angle: number \| (prevAngle) => newAngle)`|Rotate the view by the specified angle|
This react library is based on the awesome [panzoom][panzoom] by @anvaka.
The files included in this repository are licensed under the MIT license.
[]: https://github.com/anvaka/panzoom