如何在 React Native 中使用 flatlist 实现图像旋转?

how to implement the image rotary using flatlist in react native?

我正在尝试完成垂直旋转木马,如下图所示。我对第二个屏幕感到震惊,当用户从底部到顶部滚动数据时,内容和图像都会发生变化,反之亦然,如何实现这一点?期待您的帮助?enter image description here

我提供了一个小吃示例,它与您想要的大部分相似。可以使用reanimated、Flatlist实现动画:

Snack Link

代码:

import * as React from 'react';
import { Text, View, StyleSheet, FlatList, Dimensions } from 'react-native';
import Constants from 'expo-constants';
import Animated, {
  useSharedValue,
  useAnimatedScrollHandler,
  useAnimatedStyle,
  interpolate,
  Extrapolate,
} from 'react-native-reanimated';
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

const { width, height } = Dimensions.get('window');

const bottomHeight = height - 150 - 30 - Constants.statusBarHeight;

const data = [
  {
    title: 'data1',
    image:
      'https://assets.website-files.com/5f204aba8e0f187e7fb85a87/5f210a533185e7434d9efcab_hero%20img.jpg',
  },
  {
    title: 'data2',
    image:
      'https://www.whoa.in/201604-Whoa/10-alone-broken-image-mobile-wallpaper-hd-image.jpg',
  },
  {
    title: 'data3',
    image:
      'https://images.pexels.com/photos/674010/pexels-photo-674010.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
  },
  {
    title: 'data4',
    image:
      'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTntlma5HASL0HAM-KiC01A-JX4MxKousAA6A&usqp=CAU',
  },
];


const ImageContent = ({ image, scrollValue, index }) => {

  const animatedStyle = useAnimatedStyle(() => {
    const inputRange = [index * bottomHeight, (index + 1) * bottomHeight];
    const translateY = interpolate(
      scrollValue.value,
      inputRange,
      [0, -150],
      Extrapolate.CLAMP
    );
    return {
      transform: [{ translateY }],
    };
  });
  return (
    <Animated.Image
      source={{ uri: image }}
      style={[styles.image, { zIndex: data.length - index }, animatedStyle]}
      resizeMode="cover"
    />
  );
};

const TopPart = React.memo(({ scrollValue }) => {
  return (
    <View style={styles.topPartContainer}>
      {data.map(({ image }, index) => (
        <ImageContent {...{ scrollValue, image, index }} />
      ))}
    </View>
  );
});

const Item = ({ item, index }) => {
  return (
    <View
      style={[
        styles.item,
      ]}>
      <Text style={{ color: 'red' }}>{item.title}</Text>
    </View>
  );
};


const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
  topPartContainer: {
    width: 150,
    height: 150,
    borderRadius: 75,
    alignSelf: 'center',
    overflow: 'hidden',
  },
  image: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: '#fff',
    borderRadius: 75,
  },
  item: {
    width,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    height: bottomHeight,
  },
});

function App() {
  const scrollValue = useSharedValue(0);

  const handler = useAnimatedScrollHandler((event) => {
    scrollValue.value = event.contentOffset.y;
  });
  return (
    <View style={styles.container}>
      <TopPart {...{ scrollValue }} />
      <View style={{ flex: 1, paddingTop: 30, height: bottomHeight }}>
        <AnimatedFlatList
          contentContainerStyle={{ height: data.length * bottomHeight }}
          showsVerticalScrollIndicator={false}
          onScroll={handler}
          scrollEventThrottle={16}
          data={data}
          pagingEnabled
          keyExtractor={(item) => item.title}
          renderItem={({ item, index }) => <Item {...{ item, index }} />}
        />
      </View>
    </View>
  );
}