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.37k stars 2.29k forks source link

3D Cube Animation #518

Closed zek closed 1 year ago

zek commented 5 years ago

Is this a bug report, a feature request, or a question?

Question

Hello everyone,

image

I was using https://github.com/zehfernandes/react-native-3dcube-navigation library to make instagram's story like cube animation but this library doesn't use FlatList so it has performance issues and also it has some bugs. I thought maybe I can use snap-carousel to implement 3dcube navigation since it looks same as in custom interpolations page.

But when I tried to implement this custom animation. I notice _scrollInterpolator converts -1, 0, 1 to -width, 0, width. So I using "pageX - width" as given below is incorrect. I tried to change them to -1, 0, 1 but I get really weird result.

image

I am new to react native animations. Any help would be appreciated.

  _getTransformsFor = i => {
    let scrollX = this._animatedValue.x;
    let pageX = -width * i;

    let translateX = scrollX.interpolate({
      inputRange: [pageX - width, pageX, pageX + width],
      outputRange: [(-width - 1) / TR_POSITION, 0, (width + 1) / TR_POSITION],
      extrapolate: 'clamp'
    });

    let rotateY = scrollX.interpolate({
      inputRange: [pageX - width, pageX, pageX + width],
      outputRange: ['-60deg', '0deg', '60deg'],
      extrapolate: 'clamp'
    });

    let translateXAfterRotate = scrollX.interpolate({
      inputRange: [pageX - width, pageX, pageX + width],
      inputRange: [
        pageX - width,
        pageX - width + 0.1,
        pageX,
        pageX + width - 0.1,
        pageX + width
      ],
      outputRange: [
        -width - 1,
        (-width - 1) / PESPECTIVE,
        0,
        (width + 1) / PESPECTIVE,
        +width + 1
      ],
      extrapolate: 'clamp'
    });

    let opacity = scrollX.interpolate({
      inputRange: [
        pageX - width,
        pageX - width + 10,
        pageX,
        pageX + width - 250,
        pageX + width
      ],
      outputRange: [0, 0.6, 1, 0.6, 0],
      extrapolate: 'clamp'
    });

    return {
      transform: [
        { perspective: width },
        { translateX },
        { rotateY: rotateY },
        { translateX: translateXAfterRotate }
      ],
      opacity: opacity
    };
  };
zek commented 5 years ago

What I tried so far


import React, { PureComponent } from 'react';
import Carousel, { getInputRangeFromIndexes } from 'react-native-snap-carousel';
import { Dimensions, Platform, StyleSheet, View } from 'react-native';

const Window = Dimensions.get('window');

const width = Window.width;
const height = Window.height;

const PESPECTIVE = Platform.OS === 'ios' ? 2.38 : 1.7;
const TR_POSITION = Platform.OS === 'ios' ? 2 : 1.5;

const data = [
  { id: 1, color: 'red' },
  { id: 2, color: 'blue' },
  { id: 3, color: 'yellow' },
  { id: 4, color: 'green' },
  { id: 5, color: 'black' },
];

export default class MyCustomCarousel extends PureComponent {

  _scrollInterpolator(index, carouselProps) {
    const range = [1, 0, -1];
    const inputRange = getInputRangeFromIndexes(range, index, carouselProps);
    const outputRange = range;

    return { inputRange, outputRange };
  }

  _animatedStyles(i, scrollX, carouselProps) {
    let pageX = 0;

    let opacity = scrollX.interpolate({
      inputRange: [
        (pageX - width) / width,
        (pageX - width + 10) / width,
        (pageX) / width,
        (pageX + width - 250) / width,
        (pageX + width) / width,
      ],
      outputRange: [0, 0.6, 1, 0.6, 0],
      extrapolate: 'clamp',
    });

    return {
      transform: [
        {
          perspective: width,
        },
        {
          translateX: scrollX.interpolate({
            inputRange: [
              (pageX - width) / width,
              (pageX) / width,
              (pageX + width) / width,
            ],
            outputRange: [
              (-width - 1) / TR_POSITION,
              0,
              (width + 1) / TR_POSITION,
            ],
          }),
        },
        {
          rotateY: scrollX.interpolate({
            inputRange: [-1, 0, 1],
            outputRange: ['-60deg', '0deg', '60deg'],
            extrapolate: 'clamp',
          }),
        },
        {
          translateX: scrollX.interpolate({
            inputRange: [
              (pageX - width) / width,
              (pageX - width + 0.1) / width,
              pageX / width,
              (pageX + width - 0.1) / width,
              (pageX + width) / width,
            ],
            outputRange: [
              (-width - 1),
              ((-width - 1) / PESPECTIVE),
              0,
              ((width + 1) / PESPECTIVE),
              (+width + 1),
            ],
            extrapolate: 'clamp',
          }),
        },
      ],
      opacity: opacity,
    };
  }

  _renderItem({ item, index }) {
    return (
      <View key={index} style={[
        { height, top: 50, backgroundColor: item.color },
      ]}>{item.title}</View>
    );
  }

  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>

        <Carousel
          firstItem={1}
          containerCustomStyle={{ width }}
          data={data}
          useScrollView={true}
          renderItem={this._renderItem}
          sliderWidth={width}
          itemWidth={width}
          scrollInterpolator={this._scrollInterpolator}
          slideInterpolatedStyle={this._animatedStyles}
        />

      </View>
    );
  }

}
bd-arc commented 5 years ago

Hi @zek,

Can you please put all this in a Snack example? It will make it easier for us to help you :-)

zek commented 5 years ago

Here is the snack https://snack.expo.io/@drtzack/paranoid-soda

DungBuiDeveloper commented 5 years ago

you make done feature

khalidos32 commented 4 years ago

hey did any one hava an idea how we can do it with a flatlist

ghost commented 4 years ago

Do you need to complete this job? I am a 3d-cube fullstack developer. If you hire me I will best

Sent from Mailhttps://go.microsoft.com/fwlink/?LinkId=550986 for Windows 10

From: khalid aoussarmailto:notifications@github.com Sent: Sunday, December 15, 2019 8:20 PM To: archriss/react-native-snap-carouselmailto:react-native-snap-carousel@noreply.github.com Cc: michele jamesmailto:leewon961018@hotmail.com; Manualmailto:manual@noreply.github.com Subject: Re: [archriss/react-native-snap-carousel] 3D Cube Animation (#518)

hey did any one hava an idea how we can do it with a flatlist

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/archriss/react-native-snap-carousel/issues/518?email_source=notifications&email_token=ANZADAT3JYPCRHSTWGITNN3QYYOJRA5CNFSM4HL43KXKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEG4X4XY#issuecomment-565804639, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ANZADAQGCNK5J2ALA2OE7WTQYYOJRANCNFSM4HL43KXA.

romeo-balta commented 4 years ago

Try this: https://snack.expo.io/@romeobalta/3d-cube-snap

anshul-kai commented 4 years ago

I'm having a similar issue where the selected item just disappears. Below is my _slideInterpolatedStyle. If perspective is removed, everything seems to work fine... Any clue on how I could fix this?

_slideInterpolatedStyle = (index, animatedValue, carouselProps) => ({
    opacity: animatedValue.interpolate({
      inputRange: [-1, 0, 1],
      outputRange: [0.5, 1, 0.5],
      extrapolate: 'clamp',
    }),
    transform: [
      {
        perspective: animatedValue.interpolate({
          inputRange: [-1, 0, 1],
          outputRange: [-1500, 0, -1500],
          extrapolate: 'clamp',
        }),
      },
      {
        translateX: animatedValue.interpolate({
          inputRange: [-3, -2, -1, 0, 1, 2, 3],
          outputRange: [110, 50, 0, 0, 0, -50, -110],
          extrapolate: 'clamp',
        }),
      },
    ],
  });
dohooo commented 3 years ago

Sorry, please allow me to advertise for my open source library! ~ I think this library react-native-reanimated-carousel will solve your problem. It is a high performance and very simple component, complete with React-Native reanimated 2

000xuandu commented 2 years ago

Try this: https://snack.expo.io/@romeobalta/3d-cube-snap

@romeo-balta

It is exactly what we are looking for. Thanks very much. I tried writing it as a basic Flatlist/ScrollView but it didn't work as expected. Can you help me implement a Cube Animation with a basic Flatlist/ScrollView?

I wait for your response.