Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snapping between items is very jerky #189

Open
AdamPD opened this issue Oct 18, 2017 · 30 comments
Open

Snapping between items is very jerky #189

AdamPD opened this issue Oct 18, 2017 · 30 comments

Comments

@AdamPD
Copy link

AdamPD commented Oct 18, 2017

Hi guys,

I've searched around a lot and haven't found any information about this, but even the simplest of tests with the carousel I find are very jerky.

When swiping between items in the carousel, I notice that as soon as I release my finger, the speed of the snap changes. This means when I quickly flick to the next item, it instantly slows the snap speed so it looks like the swipe "hit a wall."

I'm tested this using Expo on an iPhone 7.

I've compared this to the native ScrollView with pagingEnabled or even snapToInterval and that has a much smoother effect.

Is this purely because the "snapping" action can't work out how much force a user swiped with? Or am I completely missing something?

I can probably put together an Expo snack to demonstrate the issue if need be.

@bd-arc
Copy link
Contributor

bd-arc commented Oct 18, 2017

  1. You need to understand how the plugin works: it extends the FlatList component and, therefore, the ScrollView one. Unfortunately, and as described in the doc, there are many flaws and limitations with ScrollView's implementation. This means that we have to rely on workarounds and hacks to offer even the most basic features. For example, I would love to use snapToInterval but the scrollTo() method doesn't provide callbacks of any sort, and the prop is iOS only.

  2. Never trust what you see in a debug environment. Make sure to build a production version of the app as this really smooths things out.

  3. If you want to provide a momentum-based interaction, you can set prop enableMomentum to true.

  4. I've never had any issue with nor complaints about carousel's behavior on iOS (Android is a different beast, which has been tamed recently). A screencast would definitely help me get a better understanding of the matter at stake.

  5. I can use an Expo demo to let you know if what you're experiencing is to be expected.

@eurobob
Copy link

eurobob commented Oct 23, 2017

I'm also experiencing weird behaviour on iOS. It wasn't like this a few months ago. Not sure which version i had the best success with though, I will hunt it down and report back here

@bd-arc
Copy link
Contributor

bd-arc commented Oct 23, 2017

@eurobob This is strange, because I can't reproduce the issue.

Would you mind sharing a screencast or setting up an Expo example?

@AdamPD
Copy link
Author

AdamPD commented Oct 25, 2017

@bd-arc I'll try to put together a screencast. I also see this on the showcase application. Basically, the speed of the swipe versus the speed of the snap is different, so you get this moment of switching between the swipe and the snap.

I suppose this is the best we are going to get until react-native improves ScrollView etc.

@eurobob
Copy link

eurobob commented Oct 25, 2017

I thought I had already uploaded a screencast but it must not have gone through. Attaching it to this post instead
carousel-jerk.zip

@bd-arc bd-arc removed the feedback? label Oct 25, 2017
@bd-arc
Copy link
Contributor

bd-arc commented Oct 25, 2017

@AdamPD Thanks for describing the issue in greater details.

@eurobob Thank you for taking the time to put the screencast together! You said that a previous version of the plugin wasn't affected by the issue. I'm surprised, especially because @AdamPD experiences the issue even with the showcase app that uses version 1.4.0. Still, if you can figure out which version provided a better feeling, it would help tremendously.

Unfortunately, we don't have much control over ScrollView's behavior. Particularly, there is no way to specify a duration for the scrollTo() method. As you've properly understood, this means that we can't define a snap duration that would be consistent with the swipe gesture...

I'll see what I can do about implementing pagingEnabled and snapToInterval in order to improve things on iOS. Still, I'm afraid that it might mess with the callback mechanism (a hacky way to make up for the fact that scrollTo() doesn't provide any callback...).

Your input and suggestions are most welcome ;-)

@AdamPD
Copy link
Author

AdamPD commented Oct 30, 2017

@bd-arc - I tried to implement this iOS only using snapToInterval but I ran into major issues with left and right padding. If I used contentInsets it would not snap to the right position etc. Seems like potentially a react-native bug but I gave up and went with this instead.

@JulianKingman
Copy link

JulianKingman commented Jan 25, 2018

I have a similar issue (I think it's the same issue, just more pronounced), it seems to pause mid-transition (or as soon as touch is released), and is more pronounced when the carousel is released at the mid-point between slides. The closer to the middle, the more often it happens.

@bd-arc
Copy link
Contributor

bd-arc commented Jan 26, 2018

@JulianKingman I don't think that this is the same issue. The original one has to do with how velocity and momentum are handled, while yours looks like a performance issue.

Please open another issue with a reproductible example (take a look at the contributing guidelines) and I'll gladly take a look at it.

@bd-arc
Copy link
Contributor

bd-arc commented Jan 29, 2018

@AdamPD @eurobob This seems less of an issue with the new layouts I've introduced in version 3.6.0. What do you think?

Maybe it would be possible to create a custom interpolation that would compensate for the lack of velocity handling?

@ikalangita
Copy link

Hello, I tested today the carousel from the app https://itunes.apple.com/lu/app/archriss-presentation-mobile/id1180954376?mt=8, when swiping between item it's seems not very fluid, or it's desired? does increasing the speed will remove this jerky behaviour ?

@bd-arc
Copy link
Contributor

bd-arc commented Jan 30, 2018

@ikalangita The ScrollView component - on which the plugin is ultimately based - doesn't provide any way of handling momentum, speed, velocity and such, which is pretty unfortunate.

We've implemented a bunch of workarounds, but ultimately they are just poor substitutes for the missing features. Take a look at this note if you want to know more and to vote for RN's feature requests.

As a side note, the app you've tested uses version 1.4.0 of the plugin while the current version is 3.6.0; you will notice improvements with the latest versions.

@ikalangita
Copy link

Thank you for reply, i will test the new version then :), does example provided by the repo use this latest version?

@bd-arc
Copy link
Contributor

bd-arc commented Jan 30, 2018

@ikalangita Absolutely! Also make sure to try out the brand new layout prop; this is a pretty neat feature ;-)

@JiboStore
Copy link

JiboStore commented Feb 8, 2018

@JulianKingman sorry, a bit oot, how do you achieve the full screen slider like your gif animation? I tried setting sliderWidth and itemWidth to `Dimensions.get('window').width; but seems like each item is a little bit more than the screen width, and the next item offset becomes wrong. After a few scroll I will then need one extra scroll to get to the next item...

Sorry, I found it in the documentation:
https://github.com/archriss/react-native-snap-carousel/blob/master/doc/TIPS_AND_TRICKS.md#fullscreen-slides

I just need to add the extra:
slideStyle={{ width: viewportWidth }}
inactiveSlideOpacity={1}
inactiveSlideScale={1}

@JulianKingman
Copy link

@JiboStore for reference, I just used itemWidth and sliderWidth, and had to be careful about using absolute positioning and flex sizing.

@fotoflo
Copy link

fotoflo commented Feb 18, 2018

Hi, I have a similar issue, though the movement seems smooth, the snapping is not... Snappy.

https://www.youtube.com/watch?v=zlLHIGqNdOA

@bd-arc
Copy link
Contributor

bd-arc commented Feb 18, 2018

Hi @fotoflo,

Do you mean that the carousel doesn't snap to the desired position after releasing the touch?

If so, can you open a new issue including a Snack example that reproduces the problem?

@fotoflo
Copy link

fotoflo commented Feb 18, 2018

hi @bd-arc,
actually it snaps... just happening very slowly. Also it's offcenter.

Here in the snack it seems to work better... (still off center).

Could it be because my render function is getting called whenever the props are updating? (which happens about once a second due to a websocket interaction)

https://snack.expo.io/H1LOjtwPf

@bd-arc
Copy link
Contributor

bd-arc commented Feb 19, 2018

@fotoflo It's definitely not a plugin issue. My guess is that you've inadvertently activated the "Slow animations" feature of the iOS simulator (see the "Debug" menu).

Regarding slides' alignment, you made three mistakes:

  • You didn't specify a width for your ThumbnailBackgroundView.
  • You used a RN-specific style prop (justifyContent) while declaring your styles with styled components; you should have used justify-content.
  • You're supposed to use align-items for horizontal aligment since, in React Native, flex-direction defaults to column.

Use the following and you'll be fine:

const ThumbnailBackgroundView = styled.View`
  width: 320; // same as `itemWidth`
  align-items: center;
`;

@fotoflo
Copy link

fotoflo commented Feb 19, 2018

@bd-arc Thank you, excellent debugging job! works great 👍

@fotoflo
Copy link

fotoflo commented Feb 19, 2018

Here's an updated example. I think it shows a few important things:

  1. Styling
  2. Handling onPress and onSnapToItem
  3. Controlling the carousel with the ref.

https://snack.expo.io/@fotoflo/react-native-snap-carousel-example

I'm just a beginner, so there may be things you want to change, but please feel free to use it as a more complete example.

@bd-arc
Copy link
Contributor

bd-arc commented Feb 19, 2018

Thanks @fotoflo, but are you aware of the fact that there is already an example app that features this and much more ? ;)

Note that I will soon be able to work on adding a bunch of new examples. See #257 for more info.

@fotoflo
Copy link

fotoflo commented Feb 19, 2018

Thanks @bd-arc I was aware. I took a look at that app and was lost pretty quickly (sorry, i'm more of a product manager than an engineer) .... here are my thoughts (from memory, if you don't mind).

@zidniryi
Copy link

help me how to use snap carraosel basic

@ajaykumar97
Copy link

ajaykumar97 commented Apr 18, 2019

I am also facing the similar issue. I have placed the carousel absolutely positioned on the top of a MapView(react-native-maps) with custom markers inside the MapView. When I place the carousel below the map inside a View, the snapping is smooth. But when I place it on the top of the MapView, it has jerks while snapping from one item to another. However, without custom Markers, the snapping is smooth.
I am using it something like:

...

<MapView
    ref={map => (this.map = map)}
    provider={PROVIDER_GOOGLE}
    region={this.state.region}
    style={{
        flex: 1
    }}
    customMapStyle={customMapStyle}
    loadingEnabled={true}
>
    {
     this.state.markers.map((marker, index) => {
      return (
        <Marker
            key={index}
            coordinate={{
                latitude: marker.latitude,
                longitude: marker.longitude
            }}
            image={icMarker}
        />
      );
     );
   }
</MapView>
   <View
        style={{
            position: 'absolute',
            bottom: 0
        }}
    >
        <Carousel
            ref={(c) => { this._carousel = c; }}
            data={this.props.data}
            activeSlideAlignment={'start'}
            inactiveSlideOpacity={1}
            renderItem={({ item, index }) => {
                return (
                    <ProductComponent
                        item={item}
                        index={index}
                    />
                );
            }}
            sliderWidth={size.width}
            itemWidth={((size.width * 2) / 3) - 20}
        />
    </View>

...

I am using:

"react": "16.6.3",
"react-native": "0.57.8",
"react-native-snap-carousel": "^3.7.5"

@akhila-antony
Copy link

@JulianKingman sorry, a bit oot, how do you achieve the full screen slider like your gif animation? I tried setting sliderWidth and itemWidth to `Dimensions.get('window').width; but seems like each item is a little bit more than the screen width, and the next item offset becomes wrong. After a few scroll I will then need one extra scroll to get to the next item...

Sorry, I found it in the documentation:
https://github.com/archriss/react-native-snap-carousel/blob/master/doc/TIPS_AND_TRICKS.md#fullscreen-slides

I just need to add the extra:
slideStyle={{ width: viewportWidth }}
inactiveSlideOpacity={1}
inactiveSlideScale={1}

This helps me to fix the flickering of carousel after the loop.This can also fix this issue:#368

@bd-arc
Copy link
Contributor

bd-arc commented Apr 6, 2020

Smooth scrolling will finally be a reality in the next version.

Click here to learn everything about the upcoming v4!

@16ntu1120
Copy link

@bd-arc if I set the autoplay prop to true thele animation is kind of fast that does not feel like it is animating but feels like only data in the card is changing. help needed

@dohooo

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests