From 7a02376003e985076fea244d15eb25c34c1cd153 Mon Sep 17 00:00:00 2001 From: Ivanka Todorova Date: Thu, 12 Oct 2023 12:55:26 +0300 Subject: [PATCH] feat: update reactjs to 17+, react-native to 0.72, add method `getTranslation()` --- README.md | 103 ++++++++++++- example/babel.config.js | 2 + example/package.json | 8 +- example/src/App.tsx | 114 ++++++++++++-- example/src/photo.jpg | Bin 0 -> 476222 bytes package.json | 4 +- src/index.tsx | 331 +++++++++++++++++++++++++++++++++++++++- src/math.ts | 37 +++++ src/types.d.ts | 1 + 9 files changed, 571 insertions(+), 29 deletions(-) create mode 100644 example/src/photo.jpg create mode 100644 src/math.ts diff --git a/README.md b/README.md index 45920ae..961e81b 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,114 @@ # react-native-pan-pinch-view + + npm (scoped) + A view component for React Native with pinch to zoom and drag to pan functionality. -## Installation +iOS Example App Gif Android Example App Gif + + +## 👋 Introduction + +Even though the demo shows the library used with images, it was initially designed to show ``s representing blueprints of rooms. + +- Pinch to zoom with two fingers +- Drag one finger to pan +- Keep content inside container boundaries +- Configurable minimum and maximum scale +- Methods for programmatically updating position and scale + +Thanks to `react-native-reanimated` all animations are running on the UI thread, so no fps drops are experienced. + +If you want to zoom in on images *exclusively*, in a gallery-like UI, I recommend these packages, rather than my library: + +- [`react-native-awesome-gallery`](https://github.com/Flair-Dev/react-native-awesome-gallery) +- [`react-native-image-zoom`](https://github.com/likashefqet/react-native-image-zoom) + + +## 👀 Prerequisites + +This library uses `react-native-reanimated` v3 and the latest API of `react-native-gesture-handler`. + +Before installing it, you need to install those two libraries and set them up in your project: + +- `react-native-reanimated`: [installation & setup](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation) +- `react-native-gesture-handler`: [installation & setup](https://docs.swmansion.com/react-native-gesture-handler/docs/#installation) + +## ⚙️ Installation ```sh npm install react-native-pan-pinch-view ``` -## Usage +## ✂️ Usage ```js -import { multiply } from 'react-native-pan-pinch-view'; +import PanPinchView from "react-native-pan-pinch-view"; // ... -const result = await multiply(3, 7); +const CONTAINER = { + width: 300, + height: 300, +}; + +const CONTENT = { + width: 900, + height: 400, +}; +// ... + + + + + +// ... + +const styles = StyleSheet.create({ + image: { + width: CONTENT.width, + height: CONTENT.height, + }, +}); + ``` +## ⚪ Props + +| Property | Type | Default | Description | +|---------------------|----------|-----------------------------------|---------------------------------------------| +| containerDimensions | Object | `{width: number, height:number}` | Width and height of the viewable area. | +| contentDimensions | Object | `{width: number, height:number}` | Width and height of the zoomable view. | +| minScale | Number? | `0.5` | Minimum value of scale. | +| maxScale | Number? | `4` | Maximum value of scale. | +| initialScale | Number? | `1` | Initial value of scale. | + +## 🛠 Methods + +| Method | Params | Return | Description | +|----------------|-----------------------------------------|--------|----------------------------------------------------------------------------------------------| +| scaleTo | value: number, animated: boolean | void | Sets sharedValue `scale` to `value`,
if `animated` is **true** uses `withTiming` | +| setContentSize | width: number, height: number | void | Updates sharedValue `contentSize` and overrides prop: `contentDimensions` | +| translateTo | x: number, y: number, animated: boolean | void | Updates content `translateX` / `translateY`,
if `animated` is **true** uses `withTiming` | +| setMinScale | value: number | void | Updates `minScale` value | +| setMaxScale | value: number | void | Updates `maxScale` value | +| getScale | | number | Returns current value of sharedValue `scale` | +| getTranslation | | number | Returns current value of the positioning shared values `offset` + `translation` | + +You can also refer to the app inside `example/` for a running demo of this library. + ## Contributing See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. @@ -25,7 +116,3 @@ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the ## License MIT - ---- - -Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) diff --git a/example/babel.config.js b/example/babel.config.js index b85e43d..5c9f689 100644 --- a/example/babel.config.js +++ b/example/babel.config.js @@ -17,6 +17,8 @@ module.exports = function (api) { }, }, ], + '@babel/plugin-proposal-export-namespace-from', + 'react-native-reanimated/plugin', ], }; }; diff --git a/example/package.json b/example/package.json index 5e3f2a7..655d6ea 100644 --- a/example/package.json +++ b/example/package.json @@ -12,15 +12,17 @@ "expo": "~49.0.13", "expo-status-bar": "~1.6.0", "react": "18.2.0", - "react-native": "0.72.5", "react-dom": "18.2.0", + "react-native": "0.72.5", + "react-native-gesture-handler": "~2.12.0", + "react-native-reanimated": "~3.3.0", "react-native-web": "~0.19.6" }, "devDependencies": { "@babel/core": "^7.20.0", - "babel-plugin-module-resolver": "^5.0.0", "@expo/webpack-config": "^18.0.1", - "babel-loader": "^8.1.0" + "babel-loader": "^8.1.0", + "babel-plugin-module-resolver": "^5.0.0" }, "private": true } diff --git a/example/src/App.tsx b/example/src/App.tsx index 0124498..45addcc 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,31 +1,117 @@ import * as React from 'react'; -import { StyleSheet, View, Text } from 'react-native'; -import { multiply } from 'react-native-pan-pinch-view'; +import { + Button, + Image, + SafeAreaView, + StatusBar, + StyleSheet, + View, +} from 'react-native'; +import PanPinchView from 'react-native-pan-pinch-view'; +import { useRef } from 'react'; +import type { PanPinchViewRef } from '../../src/types.js'; + +const CONTENT = { + width: 100, + height: 150, +}; + +const CONTAINER = { + width: 300, + height: 300, +}; export default function App() { - const [result, setResult] = React.useState(); + const panPinchViewRef = useRef(null); - React.useEffect(() => { - multiply(3, 7).then(setResult); - }, []); + const scaleTo = (value: number) => { + panPinchViewRef.current?.scaleTo(value); + }; + + const moveTo = (x: number, y: number) => { + panPinchViewRef.current?.translateTo(x, y); + }; return ( - - Result: {result} - + + + + + + + + +