import React, {PropTypes, Component}
from 'react';
import Animation
from './Animation';
const winWidth = Dimensions.
get(
'window').width;
const winHeight = Dimensions.
get(
'window').height;
const winRatio = winWidth
/ winHeight;
const RCTUIManager = NativeModules.UIManager;
class ZoomImage extends Component {
startCapture
: PropTypes.bool,
moveCapture
: PropTypes.bool,
responderNegotiate
: PropTypes.func,
easingFunc
: PropTypes.func,
duration
: PropTypes.number,
enableScaling
: PropTypes.bool
easingFunc
: Easing.ease,
this.enableModal
= false;
this.closeModal
= this.closeModal.
bind(this);
this.openModal
= this.openModal.
bind(this);
this.getMaxSizeByRatio
= this.getMaxSizeByRatio.
bind(this);
getMaxSizeByRatio (
ratio) {
width
: ratio
>= winRatio
? winWidth
: winWidth
/ ratio,
height
: ratio
>= winRatio
? winWidth
/ ratio
: winHeight
if (this.props.source.uri) {
Image.
getSize(this.props.source.uri, (
w,
h)
=> {
this.
setState((
state)
=> {
state.maxSize
= this.
getMaxSizeByRatio(w
/ h);
this.
setState((
state)
=> {
state.maxSize
= this.
getMaxSizeByRatio(this.props.imgStyle.width
/ this.props.imgStyle.height);
if (
!this.refs.view
|| !this.enableModal)
return;
RCTUIManager.
measure(
findNodeHandle(this.refs.view), (
x,
y,
w,
h,
px,
py)
=> {
this.originPosition
= {x, y, w, h, px, py};
<TouchableWithoutFeedback style
={this.props.imgStyle}
onPress
={this.openModal}
<View style
={this.props.style}
> source
={this.props.source}
resizeMode
={this.props.resizeMode}
style
={this.props.imgStyle}
/> visible
={this.state.isModalVisible}
onClose
={this.closeModal}
originPosition
={this.originPosition}
size
={this.state.maxSize}
minAlpha
={this.props.minAlpha}
source
={this.props.source}
duration
={this.props.duration}
easingFunc
={this.props.easingFunc}
enableScaling
={this.props.enableScaling}
/> </TouchableWithoutFeedback
> class ImageModal extends Component {
backgroundColor
: 'rgba(0, 0, 0, 1)' this._modalStyle
= JSON.
parse(
JSON.
stringify(this._initModalStyle));
this._initContentStyle
= {
this._contentStyle
= JSON.
parse(
JSON.
stringify(this._initContentStyle));
this._imgSize
= JSON.
parse(
JSON.
stringify(this._initImgSize));
this._inAnimation
= false;
this._setNativeProps
= this._setNativeProps.
bind(this);
this._closeModalByTap
= this._closeModalByTap.
bind(this);
this._closeModal
= this._closeModal.
bind(this);
this._rebounce
= this._rebounce.
bind(this);
this._touchPositionCheck
= this._touchPositionCheck.
bind(this);
this._updateNativeStyles
= this._updateNativeStyles.
bind(this);
this._pan
= PanResponder.
create({
onStartShouldSetPanResponder
: this._onStartShouldSetPanResponder.
bind(this),
onStartShouldSetPanResponderCapture : (
evt,
gestureState)
=> this.props.startCapture,
onMoveShouldSetPanResponder
: this._onMoveShouldSetPanResponder.
bind(this),
onMoveShouldSetPanResponderCapture : (
evt,
gestureState)
=> this.props.moveCapture,
onPanResponderTerminationRequest : (
evt,
gestureState)
=> true,
onPanResponderGrant
: this._handlePanResponderGrant.
bind(this),
onPanResponderMove
: this._handlePanResponderMove.
bind(this),
onPanResponderRelease
: this._handlePanResponderEnd.
bind(this),
onPanResponderTerminate
: this._handlePanResponderEnd.
bind(this),
onShouldBlockNativeResponder : (
evt,
gestureState)
=> true _onStartShouldSetPanResponder (
evt,
gestureState) {
// set responder for tapping when the drawer is open if (this._inAnimation)
return;
_onMoveShouldSetPanResponder (
evt,
gestureState) {
// custom pan responder condition function if (this._inAnimation)
return;
if (this.props.responderNegotiate
&& this.props.
responderNegotiate(evt, gestureState)
=== false)
return false;
if (this.
_touchPositionCheck(gestureState)) {
_handlePanResponderGrant(
evt,
gestureState) {
_handlePanResponderMove (
evt,
gestureState) {
const {
dy}
= gestureState;
this.
_updateNativeStyles(dy);
_handlePanResponderEnd (
evt,
gestureState) {
const {
dy}
= gestureState;
if (dy
> 0.4 * winHeight) {
this.
_closeModal(
true);
}
else if (
-dy
> 0.4 * winHeight) {
this.
_closeModal(
false);
_touchPositionCheck(
gestureState) {
const {
dx,
dy}
= gestureState;
if (
Math.
abs(dy)
<= Math.
abs(dx)) {
const {
easingFunc,
onClose}
= this.props;
let current
= this._contentStyle.style.top;
this._inAnimation
= true;
end
: isDown
? winHeight
: -winHeight,
onAnimationFrame : (
val)
=> {
this.
_updateNativeStyles(val);
this._inAnimation
= false;
this.
_setNativeProps(
true);
this.
_closeModal(
true);
const {
duration,
easingFunc}
= this.props;
let current
= this._contentStyle.style.top;
this._inAnimation
= true;
duration
: Math.
abs(current
/ winHeight)
* duration,
onAnimationFrame : (
val)
=> {
this.
_updateNativeStyles(val);
this._inAnimation
= false;
_updateNativeStyles(
dy) {
// this._contentStyle.style.left = dx; // this._contentStyle.style.right = -dx; this._contentStyle.style.top
= dy;
this._contentStyle.style.bottom
= -dy;
this._modalStyle.style.backgroundColor
= `rgba(0, 0, 0, ${ 1 - Math . abs (dy) / winHeight * 0.9 })`;
if (this.props.enableScaling) {
this._imgSize.style.width
= width
* (
1 - Math.
abs(dy
/ winHeight)
* 0.6);
this._imgSize.style.height
= height
* (
1 - Math.
abs(dy
/ winHeight)
* 0.6);
this._imgSize.style.width
= width;
this._imgSize.style.height
= height;
_setNativeProps(
isReset) {
this._contentStyle
= JSON.
parse(
JSON.
stringify(this._initContentStyle));
this._modalStyle
= JSON.
parse(
JSON.
stringify(this._initModalStyle));
this._imgSize
= JSON.
parse(
JSON.
stringify(this._initImgSize));
this.content
&& this.content.
setNativeProps(this._contentStyle);
this.mask
&& this.mask.
setNativeProps(this._modalStyle);
this.img
&& this.img.
setNativeProps(this._imgSize);
easingFunc
: Easing.ease,
onAnimationFrame : (
val)
=> {
this.mask
&& this.mask.
setNativeProps({style
: {
this._inAnimation
= false;
size // origin size of the image if (visible) { this._inAnimation
= true; }
this._initImgSize.style
= size;
onRequestClose
={onClose}
> <View style
={styles.mask} ref
={
mask => {this.mask
= mask;}} {
...this._pan.panHandlers}
> <TouchableWithoutFeedback
ref
={
ref => {this.imgContainer
= ref;}}
onPress
={this._closeModalByTap}
> ref
={
ref => {this.content
= ref;}}
style
={styles.content}
> <Image ref
={
img => {this.img
= img;}} source
={source} style
={[size, styles.img]}
/> </TouchableWithoutFeedback
> const styles = StyleSheet.
create({
backgroundColor
: 'rgba(0, 0, 0, 1)',
justifyContent
: 'center',
backgroundColor
: 'transparent' justifyContent
: 'center',
ZoomImage.ImageModal
= ImageModal;
export default ZoomImage;