meliorence / react-native-snap-carousel

Swiper/carousel component for React Native featuring previews, multiple layouts, parallax images, performant handling of huge numbers of items, and more. Compatible with Android & iOS.
BSD 3-Clause "New" or "Revised" License
10.32k stars 2.28k forks source link

Force zIndex of inactive slides to be lower than the active slide #182

Closed weswes closed 6 years ago

weswes commented 6 years ago

As I'm animating current active slide to sometime take the whole width of the screen, the right inactive slide is still upside my current item. Is there any way to force current active item zIndex to be superior than others ?

weswes commented 6 years ago

I can do it by changing render() in carousel.js:

(...)
var zIndex= 0;
if (this.currentIndex == index){
    zIndex = 1;
}
  return (
              <Animated.View
                key={`carousel-item-${index}`}
                style={[
                    slideStyle,
                  {  zIndex: zIndex,
                    opacity: animatedValue.opacity.interpolate({
                            inputRange: [0, 1],
                            outputRange: [inactiveSlideOpacity, 1]
                        }),
                        transform: [{
                            scale: animatedValue.scale.interpolate({
                                inputRange: [0, 1],
                                outputRange: [inactiveSlideScale, 1]
                            })
                        }],
                    }
                ]}>
                    { child }
              </Animated.View>
            );
(...)
bd-arc commented 6 years ago

Hi @weswes,

I can definitely add a new prop that would allow setting a higher zIndex for the active slide. Still, I think that users will be facing a problem when the indexes will change: the previous active item will instantly move behind the new active one, and this will result in a sub-par user experience. What are you thoughts about that?

By the way, which version of the plugin are you using?

bd-arc commented 6 years ago

Closing since no further feedback was provided.

radiodario commented 6 years ago

Hi @bd-arc this would be beneficial for me as well since i have an interaction which scales up the current slide on dragging up (to reveal some details) and currently this makes the next slide appear under the current one, How would you go about enabling this? I would definetely want the next and previous slides to have a lower z-index than the current:

[ 1 ] [ 2 ] [ 1 ]

bd-arc commented 6 years ago

Hi @radiodario,

You can use the new prop slideInterpolatedStyle to provide custom styles.

You can learn more about this feature in the "custom interpolations" documentation. You will also find examples with the current active slide on top of the others (make sure to read the "caveats" section though).

radiodario commented 6 years ago

thanks a lot @bd-arc! amazing work on this library 💪

haikov commented 5 years ago

Hey @bd-arc!

I'm also trying to implement similar behavior when the slide at the middle should be on top of left and right. Something like this:

image

But I can't find the way of how to make it dynamically. I defined a custome slideInterpolatedStyle and provided the following function on there:

export function animatedStyles(index, animatedValue, carouselProps) {
  let animatedOpacity = {};
  let animatedTransform = {};

  // .. do related animation configs

  return {
    // this line sets z-index to every 2nd slide, but is it possible to 
    // set this dynamically depending on the current selected slide?
    zIndex: index % 2 !== 0 ? 5 : 1,
    ...animatedOpacity,
    ...animatedTransform,
  };
}

Already spend a lot of time with it and can't figure it out, but feel that the solution is somewhere close and that's it should be easy 😕 Do you maybe have ideas about it?

Thank you in advance and thanks for such useful library!

bd-arc commented 5 years ago

Hey @gaykov,

I remember trying a few things with dynamic z-indexes but I wasn't able to come up with something totally satisfying.

Let's go further this time! Can you share a Snack example that shows what you've tried so far?

AlirezaAzizi145 commented 5 years ago

@weswes @gaykov @radiodario hello guys. i really need this style too. please help me if you found a solution. Thanks a lot

IvanMtz97 commented 4 years ago

Hello guys, i made a workaround, concious that isnt the best way to do it modifyng the state of the carousel container component, setting the onSnapToItem index to the Component state index => this.setState({ carouselCurrentItemIndex: index }) forces the whole component re-render and re validates the slideInterpolatedStyle so can use return { elevation: index === this.state.carouselCurrentItemIndex ? 1 : 0, } and everytime you slide to an item, the component state gets changed and re renders the slider with the items interpolated style and re validates the elevation validation

tomLadder commented 3 years ago

Same issue. Tried several hours. No perfect solution found.

lnroma commented 3 years ago

Hello guys, i made a workaround, concious that isnt the best way to do it modifyng the state of the carousel container component, setting the onSnapToItem index to the Component state index => this.setState({ carouselCurrentItemIndex: index }) forces the whole component re-render and re validates the slideInterpolatedStyle so can use return { elevation: index === this.state.carouselCurrentItemIndex ? 1 : 0, } and everytime you slide to an item, the component state gets changed and re renders the slider with the items interpolated style and re validates the elevation validation

elevation not for iOS

Fredy commented 3 years ago

If someone still needs this, just animate zIndex:

    zIndex: animatedValue.interpolate({
      inputRange: [-1, 0, 1],
      outputRange: [1, 5, 1],
      extrapolate: 'clamp',
    }),
sajadghawami commented 2 years ago

@Fredy

how did u do it? It doesn't work for me like this:

  const scrollInterpolator = (index: number, carouselProps: any) => {
    const range = [10, -10];
    const inputRange = getInputRangeFromIndexes(range, index, carouselProps);
    const outputRange = range;

    return { inputRange, outputRange };
  };

  const slideInterpolatedStyle = (
    index: number,
    animatedValue: any,
    carouselProps: any
  ) => {
    return {
      zIndex: animatedValue.interpolate({
        inputRange: [-1, 0, 1],
        outputRange: [1, 5, 1],
        extrapolate: "clamp",
      }),
    };
  };

The last one will still be infront of the one before

Fredy commented 2 years ago

@sajadghawami this is the entire slideInterpolatedStyle that I use:

function slideInterpolatedStyle(
  index: number,
  animatedValue: Animated.AnimatedInterpolation,
) {
  return {
    zIndex: animatedValue.interpolate({
      inputRange: [-1, 0, 1],
      outputRange: [1, 5, 1],
      extrapolate: 'clamp',
    }),
    opacity: animatedValue.interpolate({
      inputRange: [-1, 0, 1],
      outputRange: [0.3, 1, 0.3],
      extrapolate: 'clamp',
    }),
    transform: [
      {
        scale: animatedValue.interpolate({
          inputRange: [-1, 0, 1],
          outputRange: [0.75, 1, 0.75],
          extrapolate: 'clamp',
        }),
      },
      {
        translateX: animatedValue.interpolate({
          inputRange: [-1, 0, 1],
          outputRange: [100, 1, -100],
          extrapolate: 'clamp',
        }),
      },
      {
        translateY: animatedValue.interpolate({
          inputRange: [-1, 0, 1],
          outputRange: [-80, 1, -80],
          extrapolate: 'clamp',
        }),
      },
    ],
  } as unknown as StyleProp<ViewStyle>;
}
sajadghawami commented 2 years ago

@Fredy

Thanks for the quick reply!

Did u happen to use the scrollInterpolator function?

Fredy commented 2 years ago

@sajadghawami Yes:

import { getInputRangeFromIndexes } from 'react-native-snap-carousel';

function scrollInterpolator(index: number, carouselProps: any) {
  const range = [1, 0, -1];
  const inputRange = getInputRangeFromIndexes(range, index, carouselProps);
  const outputRange = range;

  return { inputRange, outputRange };
}
sajadghawami commented 2 years ago

@Fredy thank you very much! unfortunately i couldn't make it run... so i ll just leave it as it is for now

sahilrathi01 commented 1 year ago

Hey @bd-arc!

I'm also trying to implement similar behavior when the slide at the middle should be on top of left and right. Something like this:

image

But I can't find the way of how to make it dynamically. I defined a custome slideInterpolatedStyle and provided the following function on there:

export function animatedStyles(index, animatedValue, carouselProps) {
  let animatedOpacity = {};
  let animatedTransform = {};

  // .. do related animation configs

  return {
    // this line sets z-index to every 2nd slide, but is it possible to 
    // set this dynamically depending on the current selected slide?
    zIndex: index % 2 !== 0 ? 5 : 1,
    ...animatedOpacity,
    ...animatedTransform,
  };
}

Already spend a lot of time with it and can't figure it out, but feel that the solution is somewhere close and that's it should be easy 😕 Do you maybe have ideas about it?

Thank you in advance and thanks for such useful library! Screenshot 2023-06-24 at 12 02 03 PM

hey bro did you got this ? i also spend a lot of time with it and can't figure it out,, please please please please please