2.0.5 • Published 9 months ago

react-native-deck-swiper v2.0.5

Weekly downloads
1,958
License
ISC
Repository
github
Last release
9 months ago

react-native-deck-swiper

contributions welcome npm version

Installation

yarn add react-native-deck-swiper

OR

npm install react-native-deck-swiper --save

Versions info

Version 2.0.0-beta is technically version 1.7.2 of the package. However, npm recommended that due to the change in ownership the version be bumped.

react-native-deck-swiperreact-nativedescription
<= 2.0.3-beta<= 0.56.xshould install react-native-view-overflow and set useViewOverflow true
>= 2.0.4=> 0.57.xno longer requires react-native-view-overflow; useViewOverflow removed

Issues

Before submitting a new issue please check if it hasn't already been reported yet. With respect to bugfixes and further developments, please check the To Do board.

Overview

  • Rotation animation
  • Opacity animation
  • Zoom animation
  • Overlay labels
  • Show next card while swiping
  • Swipe event callbacks
  • Trigger swipe animations programmatically
  • Jump to a card index
  • Swipe to previous card
  • Underlaying cards offset
  • Never-ending, animated deck when infinite property is true
  • Swipe back to previous card with a custom animation

Preview

App preview App preview2

Props

Card props

Propstypedescriptionrequireddefault
cardsarrayarray of data for the cards to be renderedrequired
renderCardfunc(cardData, cardIndex)function to render the card based on the datarequired
keyExtractorfunc(cardData)function to get the card's react keynull
cardIndexnumbercardIndex to start with0
infiniteboolkeep swiping indefinitelyfalse
horizontalSwipeboolenable/disable horizontal swipingtrue
verticalSwipeboolenable/disable vertical swipingtrue
showSecondCardboolenable/disable second card while swipingtrue
stackSizenumbernumber of underlaying cards to show (showSecondCard must be enabled)1

Event callbacks

Propstypedescriptiondefault
onSwipedAllfuncfunction to be called when all cards have been swiped() => {}
onSwipedfuncfunction to be called when a card is swiped. it receives the swiped card index(cardIndex) => {}
onSwipedAbortedfuncfunction to be called when a card is released before reaching the threshold() => {}
onSwipedLeftfuncfunction to be called when a card is swiped left. it receives the swiped card index(cardIndex) => {}
onSwipedRightfuncfunction to be called when a card is swiped right. it receives the swiped card index(cardIndex) => {}
onSwipedTopfuncfunction to be called when a card is swiped top. it receives the swiped card index(cardIndex) => {}
onSwipedBottomfuncfunction to be called when a card is swiped bottom. it receives the swiped card index(cardIndex) => {}
onSwipingfuncfunction to be called when a card is being moved. it receives X and Y positions(x, y) => {}
dragStartfuncfunction to be called when drag start
dragEndfuncfunction to be called when drag end
onTapCardfuncfunction to be called when tapping a card. it receives the tapped card index(cardIndex) => {}
onTapCardDeadZonenumbermaximum amount of movement before a tap is no longer recognized as a tap5

Swipe animation props

Propstypedescriptiondefault
verticalThresholdnumbervertical swipe thresholdheight / 5
horizontalThresholdnumberhorizontal swipe thresholdwidth / 4
swipeAnimationDurationnumberduration of the swipe animation350
disableBottomSwipebooldisable bottom swipefalse
disableLeftSwipebooldisable left swipefalse
disableRightSwipebooldisable right swipefalse
disableTopSwipebooldisable top swipefalse

Stack props

Propstypedescriptiondefault
stackSeparationnumbervertical separation between underlaying cards10
stackScalenumberpercentage to reduce the size of each underlaying card3
stackAnimationFrictionnumberspring animation friction (bounciness)7
stackAnimationTensionnumberspring animation tension (speed)40

Rotation animation props

Propstypedescriptiondefault
inputRotationRangearrayx values range for the rotation output-width / 2, 0, width / 2
outputRotationRangearrayrotation values for the x values in inputRotationRange"-10deg", "0deg", "10deg"

Opacity animation props

Propstypedescriptiondefault
animateCardOpacityboolanimate card opacityfalse
inputCardOpacityRangeXarraypan x card opacity input range-width / 2, -width / 3, 0, width / 3, width / 2
outputCardOpacityRangeXarrayopacity values for the values in inputCardOpacityRangeX0.8, 1, 1, 1, 0.8
inputCardOpacityRangeYarraypan y card opacity input range-height / 2, -height / 3, 0, height / 3, height / 2
outputCardOpacityRangeYarrayopacity values for the values in inputCardOpacityRangeY0.8, 1, 1, 1, 0.8
animateOverlayLabelsOpacityboolanimate card overlay labels opacityfalse
inputOverlayLabelsOpacityRangeXarraypan x overlay labels opacity input range-width / 3, -width / 4, 0, width / 4, width / 3
outputOverlayLabelsOpacityRangeXarrayopacity values for the values in inputOverlayLabelsOpacityRangeX1, 0, 0, 0, 1
inputOverlayLabelsOpacityRangeYarraypan x overlay labels opacity input range-height / 4, -height / 5, 0, height / 5, height / 4
outputOverlayLabelsOpacityRangeYarrayopacity values for the values in inputOverlayLabelsOpacityRangeY1, 0, 0, 0, 1
overlayOpacityVerticalThresholdnumbervertical threshold for overlay labelheight / 5
overlayOpacityHorizontalThresholdnumberhorizontal threshold for overlay labelwidth / 4

2 steps of inputOverlayLabelsOpacityRangeX and inputOverlayLabelsOpacityRangeY should match horizontalThreshold and verticalThreshold, respectively.

Swipe overlay labels

Propstypedescriptiondefault
overlayLabelsobjectswipe labels title and stylenull, see below for format
overlayLabelStyleobjectswipe labels stylenull, see below for format
overlayLabelWrapperStyleobjectoverlay label wrapper stylesee below for default

overlayLabelStyle

{
  fontSize: 45,
  fontWeight: 'bold',
  borderRadius: 10,
  padding: 10,
  overflow: 'hidden'
}

overlayLabelWrapperStyle default props:

{
  position: 'absolute',
  backgroundColor: 'transparent',
  zIndex: 2,
  flex: 1,
  width: '100%',
  height: '100%'
}

overlayLabels default props :

{
  bottom: {
	element: <Text>BLEAH</Text> /* Optional */
	title: 'BLEAH',
    style: {
      label: {
        backgroundColor: 'black',
        borderColor: 'black',
        color: 'white',
        borderWidth: 1
      },
      wrapper: {
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center'
      }
    }
  },
  left: {
	element: <Text>NOPE</Text> /* Optional */
	title: 'NOPE',
    style: {
      label: {
        backgroundColor: 'black',
        borderColor: 'black',
        color: 'white',
        borderWidth: 1
      },
      wrapper: {
        flexDirection: 'column',
        alignItems: 'flex-end',
        justifyContent: 'flex-start',
        marginTop: 30,
        marginLeft: -30
      }
    }
  },
  right: {
	element: <Text>LIKE</Text> /* Optional */
	title: 'LIKE',
    style: {
      label: {
        backgroundColor: 'black',
        borderColor: 'black',
        color: 'white',
        borderWidth: 1
      },
      wrapper: {
        flexDirection: 'column',
        alignItems: 'flex-start',
        justifyContent: 'flex-start',
        marginTop: 30,
        marginLeft: 30
      }
    }
  },
  top: {
	element: <Text>SUPER</Text> /* Optional */
	title: 'SUPER LIKE',
    style: {
      label: {
        backgroundColor: 'black',
        borderColor: 'black',
        color: 'white',
        borderWidth: 1
      },
      wrapper: {
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center'
      }
    }
  }
}

Swipe back to previous card props

Make sure you set showSecondCard={false} for smoother and proper transitions while going back to previous card.

Propstypedescriptiondefault
goBackToPreviousCardOnSwipeLeftboolprevious card is rendered on left swipefalse
goBackToPreviousCardOnSwipeRightboolprevious card is rendered on right swipefalse
goBackToPreviousCardOnSwipeTopboolprevious card is rendered on top swipefalse
goBackToPreviousCardOnSwipeBottomboolprevious card is rendered on bottom swipefalse

Style props

Propstypedescriptiondefault
backgroundColorstringbackground color for the view containing the cards'#4FD0E9'
marginTopnumbermarginTop for the swiper container0
marginBottomnumbermarginBottom for the swiper container0
cardVerticalMarginnumbercard vertical margin60
cardHorizontalMarginnumbercard horizontal margin20
childrenOnTopboolrender children on top or notfalse
cardStylenodeoverride swipable card style{}
containerStylenodeoverrides for the containing style{}
pointerEventsstringpointerEvents prop for the containing 'auto'
useViewOverflowbooluse ViewOverflow instead of View for the Swiper componenttrue

Swipe back method info

Method

Nametypedescription
swipeBackcallbackswipe back into deck last swiped card. stacksize should be 2 cards or more

Props

Propstypedescriptiondefault
previousCardDefaultPositionXnumberAnimation start position oX when card swipes back into deck-width
previousCardDefaultPositionYnumberAnimation start position oY when card swipes back into deck-height
stackAnimationFrictionnumberspring animation friction (bounciness)7
stackAnimationTensionnumberspring animation tension (speed)40
stackAnimationTensionnumberspring animation tension (speed)40
swipeBackCardboolrenders swipe back card, in order to animate itfalse

Methods

To trigger imperative animations, you can use a reference to the Swiper component.

Nameargumentsdescription
swipeLeftmustDecrementCardIndex = falseswipe left to the next card
swipeRightmustDecrementCardIndex = falseswipe right to the next card
swipeTopmustDecrementCardIndex = falseswipe top to the next card
swipeBottommustDecrementCardIndex = falseswipe bottom to the next card
jumpToCardIndexcardIndexset the current card index

Usage example

render () {
    <View style={styles.container}>
        <Swiper
            cards={['DO', 'MORE', 'OF', 'WHAT', 'MAKES', 'YOU', 'HAPPY']}
            renderCard={(card) => {
                return (
                    <View style={styles.card}>
                        <Text style={styles.text}>{card}</Text>
                    </View>
                )
            }}
            onSwiped={(cardIndex) => {console.log(cardIndex)}}
            onSwipedAll={() => {console.log('onSwipedAll')}}
            cardIndex={0}
            backgroundColor={'#4FD0E9'}
            stackSize= {3}>
            <Button
                onPress={() => {console.log('oulala')}}
                title="Press me">
                You can press me
            </Button>
        </Swiper>
    </View>
}

Demo inside the Example Folder

Stylesheet example

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#F5FCFF"
  },
  card: {
    flex: 1,
    borderRadius: 4,
    borderWidth: 2,
    borderColor: "#E8E8E8",
    justifyContent: "center",
    backgroundColor: "white"
  },
  text: {
    textAlign: "center",
    fontSize: 50,
    backgroundColor: "transparent"
  }
});

Updating props on card content? (dynamic card content)

Card properties may change, including on already swiped cards, which would yield no effects to users as the cards would no longer be displayed [based on initial issue].

A possible fix for the situation is setting the cardIndex on the parent component whenever deck re-renders are needed.

const { cardIndex } = this.props;
return (<Swiper
  ref={swiper => {
    this.swiper = swiper;
  }}
  {...customSwiperProps}
  cardIndex={cardIndex}
/>)

Passing along the cardIndex to the swiper will allow external changes on the property, thus triggering a re-render of the deck of cards. All onSwipe callbacks return the cardIndex that can be used to push the updated cardIndex to app state (redux or something else).

By making sure that external changes on the cardIndex match those the swiper performs (increment on swipes, decrement on swipeBack) one can ensure no re-renders occur when not needed.

Development

If you've encountered issues while running the example app located in the example folder, try the following steps:

If you're using yarn 1. rm -rf node_modules && rm yarn.lock 2. yarn cache clean 3. yarn 4. react-native run-ios 5. react-native run-android

If you're using npm 1. rm -rf node_modules && rm package-lock.json 2. npm cache clean --force 3. npm install 4. react-native run-ios 5. react-native run-android

If bundler doesn't automatically start Simply run yarn start or npm start in the Example folder.

Don't forget to bump project and example versions in package.json whenever you submit a PR.

2.0.5

9 months ago

2.0.3-beta

10 months ago

2.0.2-beta

10 months ago

2.0.1-beta

10 months ago

2.0.0-beta

10 months ago

1.6.7

2 years ago

1.6.6

2 years ago

1.6.4

2 years ago

1.5.26

3 years ago

1.5.25

3 years ago

1.5.24

3 years ago

1.5.23

3 years ago

1.5.22

3 years ago

1.5.18

3 years ago

1.5.17

3 years ago

1.5.16

3 years ago

1.5.15

3 years ago

1.5.14

3 years ago

1.5.12

3 years ago

1.5.11

3 years ago

1.5.9

3 years ago

1.4.9

3 years ago

1.4.8

3 years ago

1.4.7

3 years ago

1.4.6

3 years ago

1.4.5

4 years ago

1.4.4

4 years ago

1.4.3

4 years ago

1.4.2

4 years ago

1.4.1

4 years ago

1.4.0

4 years ago

1.3.9

4 years ago

1.3.8

4 years ago

1.3.7

4 years ago

1.3.6

4 years ago

1.3.5

4 years ago

1.3.4

4 years ago

1.3.3

4 years ago

1.3.2

4 years ago

1.3.1

4 years ago

1.3.0

4 years ago

1.2.9

4 years ago

1.2.8

4 years ago

1.2.7

4 years ago

1.2.6

4 years ago

1.2.5

4 years ago

1.2.4

4 years ago

1.2.3

4 years ago

1.2.2

4 years ago

1.2.1

4 years ago

1.2.0

4 years ago

1.1.9

4 years ago

1.1.8

4 years ago

1.1.7

4 years ago

1.1.6

4 years ago

1.1.5

4 years ago

1.1.4

4 years ago

1.1.3

4 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.9

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago