diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01578a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +## generic files to ignore +*~ +*.lock +*.DS_Store +*.swp +*.out + +*.iws +workspace.xml +tasks.xml +.idea/ +.idea +Pods +Pods/ + +lto-llvm.* + +#node specific +node_modules diff --git a/README.md b/README.md index 1d20d5c..9c456c6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ -# react-native-looped-carousel -Looped carousel for React Native +# Looped carousel for React Native + +Based on [react-native framework](https://github.com/facebook/react-native/) (as of 0.3.4) by Facebook. + +### Demo +![](http://spronin.github.io/img/react.gif) + + +### Used in + - [React Native Buyscreen](https://github.com/appintheair/react-native-buyscreen) + +---- + +More on react-native here: http://facebook.github.io/react-native/docs/getting-started.html#content diff --git a/index.js b/index.js new file mode 100644 index 0000000..bd903b2 --- /dev/null +++ b/index.js @@ -0,0 +1,138 @@ +'use strict'; + +var React = require('react-native'); +var TimerMixin = require('react-timer-mixin'); +var Dimensions = require('Dimensions'); +var {width, height} = Dimensions.get('window'); + +var { + AppRegistry, + StyleSheet, + Image, + Text, + ScrollView, + View +} = React; + + +var PAGE_CHANGE_DELAY = 4000; + +/** + * Animates pages in cycle + * (loop possible if children count > 1) +*/ +var Carousel = React.createClass({ + propTypes:{ + children: React.PropTypes.node.isRequired, + delay: React.PropTypes.number, + style: View.propTypes.style + }, + mixins: [TimerMixin], + getDefaultProps: function() { + return {delay: PAGE_CHANGE_DELAY}; + }, + getInitialState: function() { + var childrenCount = this.props.children.length; + return { + contentOffset: {x: childrenCount > 1 ? width : 0, y: 0}, + currentPage: childrenCount > 1 ? 1 : 0, + }; + }, + componentDidMount:function(){ + this._setUpTimer(); + }, + _onScrollBegin: function(event) { + clearTimeout(this.timer); + }, + _onScrollEnd: function(event) { + this._setUpTimer(); + + var offset = event.nativeEvent.contentOffset; + + var childrenCount = this.props.children.length; + if (offset.x == 0) { + offset = {x: childrenCount*width, y: 0}; + } else if (offset.x == (childrenCount+1)*width) { + offset = {x: width, y: 0}; + } + + this._calculateCurrentPage(offset.x); + this.setState({contentOffset: offset}); + }, + _setUpTimer: function() { + //only for cycling + if (this.props.children.length > 1) { + clearTimeout(this.timer); + this.timer = this.setTimeout(this._animateNextPage, this.props.delay); + } + }, + _animateNextPage: function() { + var k = this.state.currentPage; + k++; + + this.setState({currentPage: k}); + this.refs.scrollView.scrollTo(0, k*width); + this._setUpTimer(); + }, + _calculateCurrentPage: function(offset) { + var page = Math.floor((offset - width/2) / width) + 1; + this.setState({currentPage: page}); + }, + //TODO: add optional `dots` for displaying current page (like pageControl) + render: function() { + var pages = []; + + var children = this.props.children; + + //to make infinite pages structure like this is needed: 3-1-2-3-1 + //add last one at the 1st place + if (children.length > 1) { + pages.push(children[children.length-1]); + } + + //add all pages + for (var i=0; i 1) { + pages.push(children[0]); + } + + pages = pages.map((page, i) => { + return {page}; + }); + + return ( + 1?2:0))} + ]} + > + {pages} + + ); + }, +}); + +var styles = StyleSheet.create({ + horizontalScroll: { + height: height, + position:'absolute' + } +}); + +module.exports = Carousel; diff --git a/package.json b/package.json new file mode 100644 index 0000000..6054603 --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "react-native-looped-carousel", + "version": "0.0.1", + "description": "Looped carousel for React Native", + "author": "Phil Rukin (http://rukin.me)", + "contributors": [{ + "name": "Sergey Pronin", + "email": "sergey@pronin.me" + }], + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/appintheair/react-native-looped-carousel" + }, + "bugs": { + "url": "https://github.com/appintheair/react-native-looped-carousel/issues" + }, + "keywords": [ + "react", + "native", + "carousel", + "looped" + ], + "tags": [ + "react", + "native", + "carousel", + "looped" + ], + "license": "MIT", + "dependencies": { + "react-native": "^0.3.4" + } +}