├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── example.gif ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | BouncyBloodExample -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | BouncyBloodExample 2 | .gitignore 3 | example.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Jan Soendermann 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bouncy View 2 | 3 | A View that bounces up and down and cycles through its children. 4 | 5 | ![react-native-bouncy-view-demo](https://raw.githubusercontent.com/jsoendermann/react-native-bouncy-view/master/example.gif) 6 | 7 | ## Usage 8 | 9 | Install with `yarn add react-native-bouncy-view` 10 | 11 | ```javascript 12 | import BouncyView from 'react-native-bouncy-view' 13 | 14 | 15 | 🍏 16 | 🥑 17 | 🥕 18 | 🍅 19 | 🐟 20 | 🥜 21 | 🍵 22 | 23 | ``` 24 | 25 | ## License 26 | 27 | ``` 28 | Copyright 2017 Jan Soendermann 29 | 30 | Licensed under the Apache License, Version 2.0 (the "License"); 31 | you may not use this file except in compliance with the License. 32 | You may obtain a copy of the License at 33 | 34 | http://www.apache.org/licenses/LICENSE-2.0 35 | 36 | Unless required by applicable law or agreed to in writing, software 37 | distributed under the License is distributed on an "AS IS" BASIS, 38 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 39 | See the License for the specific language governing permissions and 40 | limitations under the License. 41 | ``` -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsoendermann/react-native-bouncy-view/edb31ce9429b32333518070d98bff469e14825f8/example.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Animated, Easing } from 'react-native' 3 | import PropTypes from 'prop-types' 4 | 5 | export default class BouncyView extends Component { 6 | static EASING = Easing.bezier(0.13, 0.69, 0.32, 1) 7 | 8 | static propTypes = { 9 | bounceDuration: PropTypes.number, 10 | bounceHeight: PropTypes.number, 11 | } 12 | 13 | static defaultProps = { 14 | bounceDuration: 2000, 15 | bounceHeight: 50, 16 | } 17 | 18 | state = { 19 | yOffset: new Animated.Value(0), 20 | childViewIndex: 0, 21 | } 22 | 23 | componentDidMount() { 24 | this.startNextAnimation() 25 | } 26 | 27 | startNextAnimation = () => { 28 | Animated.sequence([ 29 | Animated.timing(this.state.yOffset, { 30 | toValue: 1, 31 | duration: this.props.bounceDuration / 2, 32 | easing: BouncyView.EASING, 33 | useNativeDriver: true, 34 | }), 35 | Animated.timing(this.state.yOffset, { 36 | toValue: 0, 37 | duration: this.props.bounceDuration / 2, 38 | easing: Easing.out(BouncyView.EASING), 39 | useNativeDriver: true, 40 | }), 41 | ]).start(this.animationFinished) 42 | } 43 | 44 | animationFinished = () => { 45 | this.setState( 46 | { 47 | childViewIndex: this.state.childViewIndex + 1, 48 | }, 49 | this.startNextAnimation, 50 | ) 51 | } 52 | 53 | render() { 54 | const childYOffset = this.state.yOffset.interpolate({ 55 | inputRange: [0, 1], 56 | outputRange: [0, -this.props.bounceHeight], 57 | }) 58 | 59 | let childView = this.props.children 60 | if (Array.isArray(this.props.children)) { 61 | childView = this.props.children[ 62 | this.state.childViewIndex % this.props.children.length 63 | ] 64 | } 65 | 66 | return ( 67 | 73 | {childView} 74 | 75 | ) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-bouncy-view", 3 | "version": "1.0.3", 4 | "description": "A View that bounces up and down.", 5 | "author": { 6 | "name": "Jan Soendermann", 7 | "email": "jan.soendermann+npm@gmail.com" 8 | }, 9 | "homepage": "https://github.com/jsoendermann/react-native-bouncy-view", 10 | "repository": { 11 | "type": "git", 12 | "url": "git@github.com:jsoendermann/react-native-bouncy-view.git" 13 | }, 14 | "license": "Apache-2.0", 15 | "main": "index.js", 16 | "peerDependencies": { 17 | "react": "*", 18 | "react-native": "*" 19 | }, 20 | "dependencies": { 21 | "prop-types": "^15.5.10" 22 | }, 23 | "devDependencies": { 24 | "prettier": "^1.7.4" 25 | } 26 | } 27 | --------------------------------------------------------------------------------