UNPKG

react-native-floating-image

Version:
209 lines (175 loc) 5.23 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Animated, StyleSheet, Dimensions, } from 'react-native'; import { Image } from 'react-native' const ANIMATION_END_X = Dimensions.get('window').height; const NEGATIVE_END_X = ANIMATION_END_X * -1; export class AnimatedEmoji extends Component { static propTypes = { style: PropTypes.any, path: PropTypes.array, duration: PropTypes.number, factor: PropTypes.number, selectedImg: PropTypes.array, randomSize: PropTypes.array, }; static defaultProps = { style: { top: 0, left: 150, }, factor: 1, selectedImg: [0, 5], randomSize: [1, 3], duration: 5000, factor: 2, randomSize: [1, 3], }; constructor(props) { super(props); this.imgs = []; this.state = { position: new Animated.Value(ANIMATION_END_X / 2 + ANIMATION_END_X / 10), isAnimationStarted: false }; } getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } getRandomFloat(min, max) { max *= 100; min *= 100; let res = Math.floor(Math.random() * (max - min + 1)) + min return res / 100; } generateInputRanges = (start, end, count) => { const length = start - end; const segment = length / (count - 1); const results = []; results.push(start); for (let i = count - 2; i > 0; i--) { results.push(end + segment * i); } results.push(end); return results; }; generateYOutputRange = (count) => { const results = []; for (let i = 0; i < count; i++) { results.push(Math.random() * 50); } return results; }; generateScaleOutputRange = (count) => { const results = []; for (let i = 0; i < count; i++) { results.push(Math.random() + 1); } return results; }; randomAngle = () => { let array = ['0deg', '-20deg', '20deg', '0deg', '-10deg', '10deg', '90deg'] return array[this.getRandomInt(0, array.length - 1)]; } generateAnimation = () => { this._xAnimation = this.state.position.interpolate({ inputRange: [NEGATIVE_END_X, 0], outputRange: [ANIMATION_END_X, 0] }); let randomSize = this.getRandomInt(0, 3) + 3; const inputRangeY = this.generateInputRanges(NEGATIVE_END_X, 0, randomSize); this._yAnimation = this._xAnimation.interpolate({ inputRange: inputRangeY, outputRange: this.generateYOutputRange(randomSize) }); randomSize = this.getRandomInt(0, 2) + 2; const inputRangeScale = this.generateInputRanges(NEGATIVE_END_X, 0, randomSize); this._scaleAnimation = this._xAnimation.interpolate({ inputRange: inputRangeScale, outputRange: this.generateScaleOutputRange(randomSize), extrapolate: 'clamp' }); this._opacityAnimation = this._xAnimation.interpolate({ inputRange: [NEGATIVE_END_X, NEGATIVE_END_X/4*3, NEGATIVE_END_X/4*2, NEGATIVE_END_X/4, 0], outputRange: [1, 1, 1, 0.8, 0.5] }); this._rotateAnimation = this._xAnimation.interpolate({ inputRange: [NEGATIVE_END_X, NEGATIVE_END_X/4*3, NEGATIVE_END_X/4*2, NEGATIVE_END_X/4, 0], outputRange: [this.randomAngle(), this.randomAngle(), this.randomAngle(), this.randomAngle(), this.randomAngle()] }); }; calculeRandomSize() { return this.getRandomFloat(this.props.randomSize[0], this.props.randomSize[1]); } loadImg() { for (let i = 0; i != this.props.path.length; i++) { let tmpRadomSize = this.calculeRandomSize(); this.imgs.push(<Image source={this.props.path[i]} style={{ width: 9 * this.props.factor * tmpRadomSize, height: 8 * this.props.factor * tmpRadomSize }} />) } } componentDidMount() { this.loadImg(); this.startAnimating(); } startAnimating = () => { this.generateAnimation(); this.setState({ isAnimationStarted: true }, () => { Animated.timing(this.state.position, { duration: this.props.duration, toValue: -400, useNativeDriver: true }).start(() => { this.setState({ isAnimationStarted: false, position: new Animated.Value(ANIMATION_END_X), }); }); }); }; getAnimationStyle = () => { if (this.state.isAnimationStarted) { return { transform: [ { translateY: this.state.position }, { translateX: this._yAnimation }, { scale: this._scaleAnimation }, { rotate: this._rotateAnimation } ], opacity: this._opacityAnimation } } return {}; }; whichImgPrint() { if (this.props.selectedImg.length > 1) return this.getRandomInt(this.props.selectedImg[0], this.props.selectedImg[1]); return this.props.selectedImg[0]; } render() { const { style } = this.props; return ( <Animated.View style={[styles.container, this.getAnimationStyle(), style]}> {this.imgs[this.whichImgPrint()]} </Animated.View> ); } } const styles = StyleSheet.create({ container: { position: 'absolute', bottom: 0, transform: [ { translateX: ANIMATION_END_X } ], } });