react-native-imagebox
Version:
huhuge
457 lines (397 loc) • 12.4 kB
JavaScript
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Animated, Dimensions, Modal, PanResponder, Platform, StatusBar, StyleSheet, Text, TouchableOpacity, View,Image,InteractionManager ,CameraRoll} from 'react-native';
const WINDOW_HEIGHT = Dimensions.get('window').height;
const WINDOW_WIDTH = Dimensions.get('window').width;
const DRAG_DISMISS_THRESHOLD = 150;
const STATUS_BAR_OFFSET = (Platform.OS === 'android' ? -25 : 0);
const isIOS = Platform.OS === 'ios';
// const RNFS = require('react-native-fs');
// const storeLocation = `${RNFS.DocumentDirectoryPath}`;
import Swiper from 'react-native-swiper';
import ImageZoom from 'react-native-image-pan-zoom';
let BUTTONS = ["分享到朋友圈", "分享给好友", "保存相册到本地", "取消"];
let DESTRUCTIVE_INDEX = 4;
let CANCEL_INDEX = 3;
let _this = null
const renderPagination = (index, total, context) => {
return (
<View style={{
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
top: 25,
left: 0,
right: 0
}}>
<View style={{
borderRadius: 7,
backgroundColor: 'rgba(255,255,255,.15)',
padding: 3,
paddingHorizontal: 7
}}>
<Text style={{
color: '#fff',
fontSize: 14
}}>{index + 1} / {total}</Text>
</View>
</View>
)
};
let modelTimer = null
const styles = StyleSheet.create({
background: {
position: 'absolute',
top: 0,
left: 0,
width: WINDOW_WIDTH,
height: WINDOW_HEIGHT
},
open: {
position: 'absolute',
flex: 1,
justifyContent: 'center',
// Android pan handlers crash without this declaration:
backgroundColor: 'transparent',
},
header: {
position: 'absolute',
top: 0,
left: 0,
width: WINDOW_WIDTH,
backgroundColor: 'transparent',
},
closeButton: {
fontSize: 35,
color: 'white',
lineHeight: 40,
width: 40,
textAlign: 'center',
shadowOffset: {
width: 0,
height: 0,
},
shadowRadius: 1.5,
shadowColor: 'black',
shadowOpacity: 0.8
},
footDownload:{
height:60,
width:Dimensions.get('window').width,
backgroundColor:"#9C9C9C",
position:'absolute',bottom:0,
justifyContent:'center',
alignItems:'center'
},
wrapper: {
// backgroundColor: '#000',
backgroundColor: 'black',
top: 0,
right: 0,
bottom: 0,
left: 0
},
});
let fristPress = true
var timers = null
let imageHeight = 0
let imageWidth = 0
export default class OverlayImagebox extends Component {
static propTypes = {
origin: PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number,
width: PropTypes.number,
height: PropTypes.number,
}),
springConfig: PropTypes.shape({
tension: PropTypes.number,
friction: PropTypes.number,
}),
backgroundColor: PropTypes.string,
isOpen: PropTypes.bool,
renderHeader: PropTypes.func,
onOpen: PropTypes.func,
onClose: PropTypes.func,
swipeToDismiss: PropTypes.bool,
imagesource : PropTypes.string,
imageWidth : PropTypes.number,
imageHeight : PropTypes.number,
timelineShare : PropTypes.func,
sessionShare : PropTypes.func,
};
static defaultProps = {
springConfig: { tension: 30, friction: 7 },
backgroundColor: 'black',
};
state = {
isAnimating: false,
isPanning: false,
target: {
x: 0,
y: 0,
opacity: 1,
},
pan: new Animated.Value(0),
openVal: new Animated.Value(0),
imageWidth: this.props.imageWidth,
imageHeight: this.props.imageHeight,
imagesource: this.props.imagesource,
width:Dimensions.get('window').width,
height:Dimensions.get('window').height,
bounceValue: new Animated.Value(0),
showIamge : this.props.imagesource,
footView: new Animated.Value(0),
_this : this,
showOne : true,
images : this.props.images,
showIndex : 0
};
constructor(props){
super(props)
this.lastPositionX = null
this.lastPositionY = null
this.zoomCurrentDistance = null
this.zoomLastDistance = null
this.lastTouchStartTime = new Date().getTime()
this.scale = 1
this.zoomLastDistance = 0
this.springValue = new Animated.Value(1)
imageHeight = this.props.imageHeight
imageWidth = this.props.imageWidth
imagesource = this.props.imagesource
}
componentWillMount() {
this.state.bounceValue.setValue(4); // 设置一个较大的初始值
Animated.spring( // 可选的基本动画类型: spring, decay,
this.state.bounceValue, // 将`bounceValue`值动画化
{
toValue: 1, // 将其值以动画的形式改到一个较小值
// friction: 0 // Bouncier spring
}
).start();
this._panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: (evt, gestureState) => !this.state.isAnimating,
onStartShouldSetPanResponderCapture: (evt, gestureState) => !this.state.isAnimating,
onMoveShouldSetPanResponder: (evt, gestureState) => !this.state.isAnimating,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => !this.state.isAnimating,
onStartShouldSetResponder :(evt)=>true,
// onResponderMove : (evt) => this.onResponderMove(evt),
onPanResponderMove : (evt,gestureState) => this.onResponderMove(evt,gestureState),
onPanResponderGrant: (evt, gestureState) => {
this.state.pan.setValue(0);
this.setState({ isPanning: true });
},
onPanResponderMove: Animated.event([
null,
{ dy: this.state.pan }
]),
// 有其他组件请求接替响应者,当前的View是否“放权”?返回true的话则释放响应者权力。
onPanResponderTerminationRequest: (evt, gestureState) => true,
// 手指抬起离开屏幕
onPanResponderRelease: (evt, gestureState) => {
if(Math.abs(gestureState.dy) > DRAG_DISMISS_THRESHOLD) {
this.setState({
isPanning: false,
target: {
y: gestureState.dy,
x: gestureState.dx,
opacity: 1 - Math.abs(gestureState.dy / WINDOW_HEIGHT)
}
});
this.close();
} else {
Animated.spring(
this.state.pan,
{ toValue: 0, ...this.props.springConfig }
).start(() => { this.setState({ isPanning: false }); });
}
}
});
}
componentDidMount() {
if(this.props.isOpen) {
this.open();
}
}
open = () => {
if(isIOS) {
StatusBar.setHidden(true, 'fade');
}
this.state.pan.setValue(0);
this.setState({
isAnimating: true,
showOne : false,
target: {
x: 0,
y: 0,
opacity: 1,
}
});
Animated.spring(
this.state.openVal,
{ toValue: 1, ...this.props.springConfig }
).start(() => this.setState({ isAnimating: false }))
}
close = () => {
if(isIOS) {
StatusBar.setHidden(false, 'fade');
}
this.setState({
isAnimating: true,
showOne : true,
});
Animated.spring(
this.state.openVal,
{ toValue: 0, ...this.props.springConfig }
).start(() => {
this.setState({
isAnimating: false,
showOne : false
});
this.props.onClose();
});
}
componentWillReceiveProps(props) {
if(this.props.isOpen != props.isOpen && props.isOpen) {
this.open();
}
}
onResponderMove(evt,gestureState){
if (evt.nativeEvent.changedTouches.length <= 1) {
console.log("1个手指点击")
} else {
console.log("两个手指点击")
}
}
showBottom(){
this.ActionSheet.show()
}
swiperImage(){
const {images,imagesource} = this.state
let imageArray = []
if(images&&images.length>0){
images.forEach((element,index) => {
imageArray.push(
<ImageZoom key = {index} cropWidth={Dimensions.get('window').width}
cropHeight={Dimensions.get('window').height}
imageWidth={Dimensions.get('window').width}
imageHeight={Dimensions.get('window').height}>
<TouchableOpacity onPress={this.close}>
<Image style={{width:Dimensions.get('window').width,height:Dimensions.get('window').height}} source={{uri:element}} resizeMode="contain"/>
</TouchableOpacity>
</ImageZoom>
)
});
}
return imageArray
}
onScrollBeginDrag(e,state,context){
}
closeModel(){
if(modelTimer){
this.timer && clearTimeout(this.timer)
modelTimer = null
}else{
modelTimer = "closetemp"
this.timer = setTimeout(() => {
this.close()
modelTimer = null
},1000)
}
}
componentWillUnmount () {
this.timer && clearTimeout(this.timer)
}
showImage(){
const {images,imagesource,showOne} = this.state
this.state.showIndex = this.props.showIndex
if(showOne){
return <Animated.Image style={{flex: 1,transform: [{scale: this.state.bounceValue}]}} source={{uri:imagesource}} resizeMode="contain"/>
}else{
return (
<View style={{width:Dimensions.get('window').width,height:Dimensions.get('window').height}} >
<Swiper style = {styles.wrapper} showsButtons={false} autoplay = {false} index = {this.props.showIndex}
onScrollBeginDrag = {(e,state,context)=>{this.onScrollBeginDrag(e,state,context)}}
renderPagination={renderPagination}>
{this.swiperImage()}
</Swiper>
</View>
)
}
}
render() {
const {
isOpen,
renderHeader,
swipeToDismiss,
origin,
backgroundColor
} = this.props;
const {
isPanning,
isAnimating,
openVal,
target,
imageHeight,
imageWidth,
imagesource
} = this.state;
const lightboxOpacityStyle = {
opacity: openVal.interpolate({inputRange: [0, 1], outputRange: [0, target.opacity]})
};
let handlers;
if(swipeToDismiss) {
handlers = this._panResponder.panHandlers;
}
let dragStyle;
if(isPanning) {
dragStyle = {
top: this.state.pan,
};
lightboxOpacityStyle.opacity = this.state.pan.interpolate({inputRange: [-WINDOW_HEIGHT, 0, WINDOW_HEIGHT], outputRange: [0, 1, 0]});
}
const openStyle = [styles.open, {
//动画篡改 插入数据
left: openVal.interpolate({inputRange: [0, 1], outputRange: [origin.x, target.x]}),
top: openVal.interpolate({inputRange: [0, 1], outputRange: [origin.y + STATUS_BAR_OFFSET, target.y + STATUS_BAR_OFFSET]}),
width: openVal.interpolate({inputRange: [0, 1], outputRange: [origin.width, WINDOW_WIDTH]}),
height: openVal.interpolate({inputRange: [0, 1], outputRange: [origin.height, WINDOW_HEIGHT]}),
}];
const background = (<Animated.View style={[styles.background, { backgroundColor: backgroundColor }, lightboxOpacityStyle]}></Animated.View>);
const header = (<Animated.View style={[styles.header, lightboxOpacityStyle]}>{(renderHeader ?
renderHeader(this.close) :
(
<View style={{flexDirection:'row',justifyContent:"space-between" }} >
<Text style={styles.closeButton} onPress={this.close} >×</Text>
<Text style={[styles.closeButton,{marginRight:10}]}>...</Text>
</View>
)
)}</Animated.View>);
const shareView = (
<View style={{height:WINDOW_HEIGHT,width:WINDOW_WIDTH,backgroundColor:'red'}}>
</View>
)
//{...handlers}
const content = (
<Animated.View style={[openStyle, dragStyle]}>
{this.showImage()}
</Animated.View>
);
if (this.props.navigator) {
return (
<View>
{background}
{content}
</View>
);
}
return (
<Modal visible={isOpen} transparent={true} onRequestClose={() => this.close()}>
{background}
{content}
</Modal>
);
}
}