forked from DuDigital/react-native-zoomable-view
-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathApp.tsx
95 lines (86 loc) · 3.61 KB
/
App.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import React, { useCallback, useRef, useState } from 'react';
import { View, Text, Image, Animated, Button } from 'react-native';
import { ReactNativeZoomableView } from '@openspacelabs/react-native-zoomable-view';
import { styles } from './style';
import { debounce } from 'lodash';
import { applyContainResizeMode } from '../src/helper/coordinateConversion';
const kittenSize = 800;
const uri = `https://placekitten.com/${kittenSize}/${kittenSize}`;
const imageSize = { width: kittenSize, height: kittenSize };
const stringifyPoint = (point?: { x: number; y: number }) =>
point ? `${Math.round(point.x)}, ${Math.round(point.y)}` : 'Off map';
export default function App() {
const zoomAnimatedValue = useRef(new Animated.Value(1)).current;
const scale = Animated.divide(1, zoomAnimatedValue);
const [showMarkers, setShowMarkers] = useState(true);
const [size, setSize] = useState<{ width: number; height: number }>({
width: 0,
height: 0,
});
// Use layout event to get centre point, to set the pin
const [pin, setPin] = useState({ x: 0, y: 0 });
const [movePin, setMovePin] = useState({ x: 0, y: 0 });
// Debounce the change event to avoid layout event firing too often while dragging
const debouncedUpdatePin = useCallback(() => debounce(setPin, 10), [])();
const debouncedUpdateMovePin = useCallback(
() => debounce(setMovePin, 10),
[]
)();
const staticPinPosition = { x: size.width / 2, y: size.height / 2 };
const { size: contentSize } = applyContainResizeMode(imageSize, size);
return (
<View style={styles.container}>
<Text>ReactNativeZoomableView</Text>
<View
style={styles.box}
onLayout={(e) => {
setSize(e.nativeEvent.layout);
}}
>
<ReactNativeZoomableView
disableMomentum
// Where to put the pin in the content view
staticPinPosition={staticPinPosition}
// Callback that returns the position of the pin
// on the actual source image
onStaticPinPositionChange={debouncedUpdatePin}
onStaticPinPositionMove={debouncedUpdateMovePin}
maxZoom={30}
// Give these to the zoomable view so it can apply the boundaries around the actual content.
// Need to make sure the content is actually centered and the width and height are
// measured when it's rendered naturally. Not the intrinsic sizes.
contentWidth={contentSize?.width ?? 0}
contentHeight={contentSize?.height ?? 0}
panBoundaryPadding={500}
zoomAnimatedValue={zoomAnimatedValue}
>
<View style={styles.contents}>
<Image style={styles.img} source={{ uri }} />
{showMarkers &&
['20%', '40%', '60%', '80%'].map((left) =>
['20%', '40%', '60%', '80%'].map((top) => (
<Animated.View
key={`${left}x${top}`}
// These markers will move and zoom with the image, but will retain their size
// because of the scale transformation.
style={[
styles.marker,
{ left, top, transform: [{ scale }] },
]}
/>
))
)}
</View>
</ReactNativeZoomableView>
</View>
<Text>onStaticPinPositionChange: {stringifyPoint(pin)}</Text>
<Text>onStaticPinPositionMove: {stringifyPoint(movePin)}</Text>
<Button
title={`${showMarkers ? 'Hide' : 'Show'} markers`}
onPress={() => {
setShowMarkers((value) => !value);
}}
/>
</View>
);
}