├── .editorconfig ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json ├── rollup.config.js ├── src ├── ReactNativeZoomableView.tsx ├── ReactNativeZoomableViewWithGestures.tsx ├── index.tsx └── typings │ └── index.d.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see 2 | # https://editorconfig-specification.readthedocs.io/en/latest/#supported-pairs 3 | 4 | root = true 5 | 6 | [**] 7 | charset = utf-8 8 | indent_size = 2 9 | indent_style = space 10 | 11 | [{src/**,test/**}] 12 | end_of_line = lf 13 | insert_final_newline = true 14 | trim_trailing_whitespace = true 15 | 16 | [*.md] 17 | trim_trailing_whitespace = unset 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | node_modules 4 | yarn.lock 5 | package-lock.json 6 | dist -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "endOfLine": "crlf", 4 | "quoteProps": "consistent", 5 | "singleQuote": true, 6 | "trailingComma": "all" 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 DuAgentur 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚩🚩🚩 Attention: Deprecated 🚩🚩🚩 2 |

Sadly we are not using react-native in any of our projects anymore and therefore don't use this either. We tried to apply some fixes from time to time, but it took up way more time than we have available for a fun project. We also wanted to do a complete rewrite using react-animated for performance reasons, but we never made it past a prototype. Since we did not find enough contributors to keep the project alive and did not want to leave the users hanging, we decided to deprecate our codebase and talk to some of the people, who have forked and worked on it.

3 |

Fortunately the awesome guys from [openspacelabs](https://github.com/openspacelabs/) have used this package and extended it in their repo. We have talked to them and they have agreed that now have their fork is the defacto successor of react-native-zoomable-view.
4 |
There is also a reanimated version, with a (as far as I can see bit smaller feature set - but it might be perfect for you) available: https://github.com/kesha-antonov/react-native-zoom-reanimated

5 | Please only use their package going forward: https://github.com/openspacelabs/react-native-zoomable-view .
6 | This package will not be developed anymore and as soon as their npm package is published, we will archive our npm package.

7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 | 16 | # react-native-zoomable-view 17 | 18 | A view component for react-native with pinch to zoom, tap to move and double tap to zoom capability. 19 | You can zoom everything, from normal images, text and more complex nested views. 20 | 21 | We are using this component already in production in two of our projects, but for quality assurance sake, please consider this component beta. 22 | We are happy to hear from you about bugs, issues and would also appreciate your pull requests, if you've made improvements or fixed bugs. 23 | 24 | ## Preview 25 | 26 | ![](https://thumbs.gfycat.com/PalatableMeanGnat-size_restricted.gif) 27 | 28 | ## Getting started 29 | 30 | - [Installation](#installation) 31 | - [Basic Usage](#basic-usage) 32 | - [Props](#props) 33 | - [Events](#events) 34 | - [Pan Responder Hooks](#pan-responder-hooks) 35 | - [Example](#example) 36 | - [Expo Snack Example](#expo-snack-example) 37 | - [Example Repo](#example-repo) 38 | 39 | ### Installation 40 | 41 | `$ npm install @dudigital/react-native-zoomable-view --save` 42 | 43 | or 44 | 45 | `$ yarn add @dudigital/react-native-zoomable-view` 46 | 47 | ### Basic Usage 48 | 49 | This component is based on react-natives View, enhanced by panresponders and other events to make it zoomable. 50 | Therefore no platform specific configuration needs to be done. 51 | 52 | Just use it as a drop in component instead of a normal view. 53 | 54 | Import ReactNativeZoomableView: 55 | ```JSX 56 | import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; 57 | ``` 58 | 59 | Use the component: 60 | ```JSX 61 | 73 | This is the content 74 | 75 | ``` 76 | 77 | ### Example 78 | 79 | Here is a full drop in example you can use in Expo, after installing the package. 80 | 81 | ```JSX 82 | import React from 'react'; 83 | import { View, Image } from 'react-native'; 84 | import ReactNativeZoomableView from '@dudigital/react-native-zoomable-view/src/ReactNativeZoomableView'; 85 | 86 | export default class App extends React.Component { 87 | /** 88 | * Log out an example event after zooming 89 | * 90 | * @param event 91 | * @param gestureState 92 | * @param zoomableViewEventObject 93 | */ 94 | logOutZoomState = (event, gestureState, zoomableViewEventObject) => { 95 | console.log(''); 96 | console.log(''); 97 | console.log('-------------'); 98 | console.log('Event: ', event); 99 | console.log('GestureState: ', gestureState); 100 | console.log('ZoomableEventObject: ', zoomableViewEventObject); 101 | console.log(''); 102 | console.log(`Zoomed from ${zoomableViewEventObject.lastZoomLevel} to ${zoomableViewEventObject.zoomLevel}`); 103 | } 104 | 105 | render() { 106 | return ( 107 | 108 | 120 | 123 | 124 | 125 | ); 126 | } 127 | } 128 | ``` 129 | 130 | ### Expo Snack Example 131 | 132 | https://snack.expo.io/SkltQtr8Q 133 | 134 | ### Example Repo 135 | 136 | https://github.com/DuDigital/react-native-zoomable-view-example 137 | 138 | 139 | ### Props 140 | 141 | #### Options 142 | 143 | These options can be used to limit and change the zoom behavior. 144 | 145 | | name | type | description | default | 146 | | ---- | ----------- | ------ | --------------- | 147 | | zoomEnabled | boolean | Can be used to enable or disable the zooming dynamically | true | 148 | | initialZoom | number | Initial zoom level on startup | 1.0 | 149 | | maxZoom | number | Maximum possible zoom level (zoom in). Can be set to `null` to allow unlimited zooming | 1.5 | 150 | | minZoom | number | Minimum possible zoom level (zoom out) | 0.5 | 151 | | doubleTapDelay | number | How much delay will still be recognized as double press (ms) | 300 | 152 | | doubleTapZoomToCenter | boolean | If true, double tapping will always zoom to center of View instead of the direction it was double tapped in 153 | | bindToBorders | boolean | If true, it makes sure the object stays within box borders | true | 154 | | zoomStep | number | How much zoom should be applied on double tap | 0.5 | 155 | | pinchToZoomInSensitivity | number | the level of resistance (sensitivity) to zoom in (0 - 10) - higher is less sensitive | 3 | 156 | | pinchToZoomOutSensitivity | number | the level of resistance (sensitivity) to zoom out (0 - 10) - higher is less sensitive | 1 | 157 | | zoomCenteringLevelDistance | number | the (zoom level - 0 - maxZoom) distance for pinch to zoom actions until they are shifted on new pinch to zoom center - higher means it centeres slower | 0.5 | 158 | | movementSensibility | number | how resistant should shifting the view around be? (0.5 - 5) - higher is less sensitive | 1.9 | 159 | | initialOffsetX | number | The horizontal offset the image should start at | 0 | 160 | | initialOffsetY | number | The vertical offset the image should start at | 0 | 161 | | longPressDuration | number | Duration in ms until a press is considered a long press | 700 | 162 | | captureEvent | boolean | Defines whether the pan responder of the parent element should be captured. (useful for react-native modals, set it to true) | false | 163 | 164 | #### Callbacks 165 | 166 | These events can be used to work with data after specific events. 167 | 168 | | name | description | params | expected return | 169 | | ---- | ----------- | ------ | --------------- | 170 | | onDoubleTapBefore | Will be called, at the start of a double tap | event, gestureState, zoomableViewEventObject | void | 171 | | onDoubleTapAfter | Will be called at the end of a double tap | event, gestureState, zoomableViewEventObject | void | 172 | | onShiftingBefore | Will be called, when user taps and moves the view, but before our view movement work kicks in (so this is the place to interrupt movement, if you need to) | event, gestureState, zoomableViewEventObject | {boolean} if this returns true, ZoomableView will not process the shift, otherwise it will | 173 | | onShiftingAfter | Will be called, when user taps and moves the view, but after the values have changed already | event, gestureState, zoomableViewEventObject | void | 174 | | onShiftingEnd | Will be called, when user stops a tap and move gesture | event, gestureState, zoomableViewEventObject | void | 175 | | onZoomBefore | Will be called, while the user pinches the screen, but before our zoom work kicks in (so this is the place to interrupt zooming, if you need to) | event, gestureState, zoomableViewEventObject | {boolean} if this returns true, ZoomableView will not process the pinch, otherwise it will | 176 | | onZoomAfter | Will be called, while the user pinches the screen, but after the values have changed already | event, gestureState, zoomableViewEventObject | {boolean} if this returns true, ZoomableView will not process the pinch, otherwise it will | 177 | | onZoomEnd | Will be called after pinchzooming has ended | event, gestureState, zoomableViewEventObject | {boolean} if this returns true, ZoomableView will not process the pinch, otherwise it will | 178 | | onLongPress | Will be called after the user pressed on the image for a while | event, gestureState | void | 179 | 180 | 181 | #### Events 182 | 183 | The following events allow you to control the ZoomableView zoom level & position from your component. 184 | (think of control buttons, ...) 185 | 186 | You can find an implementation example in the example repo: https://github.com/DuDigital/react-native-zoomable-view-example 187 | 188 | | name | description | params | expected return | 189 | | ---- | ----------- | ------ | --------------- | 190 | | zoomTo | Changes the zoom level to a specific number | newZoomLevel: number, bindToBorders = true | Promise | 191 | | zoomBy | Changes the zoom level relative to the current level (use positive numbers to zoom in, negative numbers to zoom out) | zoomLevelChange: number, bindToBorders = true | Promise | 192 | | moveTo | Shifts the zoomed part to a specific point (in px relative to x: 0, y: 0) | newOffsetX: number, newOffsetY: number, bindToBorders = true | Promise | 193 | | moveBy | Shifts the zoomed part by a specific pixel number | newOffsetX: number, newOffsetY: number, bindToBorders = true | Promise | 194 | 195 | 196 | **Example:** 197 | 198 | ```TSX 199 | 200 | export default function App() { 201 | // you will need a reference to the ReactNativeZoomableView component 202 | const zoomableViewRef = createRef(); 203 | 204 | return ( 205 | 206 | 207 | 211 | HelloWorld 212 | 213 | 214 | 215 | 216 | {/* Here you see some examples of moveBy */} 217 |