react-native-animated-image-viewer v1.0.5
Note
resizeMode
This doesn't support all resizeMode of the source (pre-zoomed) Image component yet.
To have a proper animation effect, please render the Image in the original aspect rario.
Otherwise, please try either cover or contain.
Now landscape images will work with resizeMode: contain and portrait images will work with resizeMode: cover
Status Bar on Android
There is a famoust known issue about status bar isn't hidden on Adnroid Modal. So I need a props to know if the source (pre-zoomed) image is rendered in translucent status bar or not. Default will be true to be consistent with iOS.
Try it out
https://snack.expo.io/@origamih/animated-image-viewer
Getting Started
Installation
npm i react-native-animated-image-viewer --saveor
yarn add react-native-animated-imageBasic Usage
- Get the actual image
widthandheightusingImagecomponent:
import { Image } from 'react-native';
...
_imageSize = {
width: 0,
height: 0
};
componentDidMount () {
Image.getSize(source, (width, height) => {
this._imageSize = {
width,
height
}
});
}- Measure the absolute position of the Image to be shown right before zooming it in (as position might change. Eg: ScrollView):
import { View, Image } from 'react-native';
import React from 'react';
_sourceMeasure = {
width: 0,
height: 0,
pageX: 0,
pageY: 0
}
_showImage = () => {
this.image.measure((x, y, width, height, pageX, pageY) => {
this._sourceMeasure = {
width,
height,
pageX,
pageY
};
this._showImageModal();
});
};
return (
<TouchableOpacity ref={image => (this.image = image)} onPress={this._showImage}>
<Image source={source} style={{width: 100, height: 100}}/>
</TouchableOpacity>
);I don't use state for _imageSize and _sourceMeasure, this is more optimized since they don't trigger any UI update.
- Then show the Image in a
transparent Modal:
import { Modal, Image, TouchableOpacity, View } from 'react-native';
import React from 'react';
export default class App extends React.Component {
state = {
visible: false
}
_imageSize = {
width: 0,
height: 0
};
_sourceMeasure = {
width: 0,
height: 0,
pageX: 0,
pageY: 0
}
_showImageModal = () => this.setState({ visible: true });
_hideImageModal = () => this.setState({ visible: false });
_requestClose = () => this.imageModal.close();
_showImage = () => {
this.image.measure((x, y, width, height, pageX, pageY) => {
this._sourceMeasure = {
width,
height,
pageX,
pageY
};
this._showImageModal();
});
};
componentDidMount () {
Image.getSize(source.uri, (width, height) => {
this._imageSize = {
width,
height
}
});
}
render () {
return (
<View>
<TouchableOpacity
ref={image => (this.image = image)}
onPress={this._showImage}
>
<Image source={source} style={{width: 100, height: 100}}/>
</TouchableOpacity>
<Modal visible={this.state.visible} transparent onRequestClose={this._requestClose}>
<AnimatedImage
ref={imageModal => (this.imageModal = imageModal)}
source={source}
sourceMeasure={this._sourceMeasure}
imageSize={this._imageSize}
onClose={this._hideImageModal}
/>
</Modal>
</View>
)
}
}Props
| name | type | required | description | default |
|---|---|---|---|---|
| onClose | function() => void | yes | Invoked when close transition is done. Usually this is used to close Modal | |
| source | object | yes | source for Image | |
| sourceMeasure | object{pageX: number, pageY: number, width: number, height: number} | yes | Absolute position and dimension of the source image component | |
| imageSize | object{width: number, height: number} | no | Actual image size | |
| Menu | React Element | no | Header menu for the zoomed in image | null |
| animationDuration | number | no | Animation duration | 200 |
| translucentStatusBar | bool | no | Android only. Used to calculated the top padding caused by non-translucent status bar | true |
Methods
| name | description |
|---|---|
| close() | Close Modal with animation. Useful for Android onRequestClose |
Credit
ImagePinchZoomcomponent is rewritten from react-native-image-pan-zoom. The original package is TypeScript which I'm not familiar with. So I transpiled it into ES6, then made some modifications to match the need.Inspired by Narendra N Shetty