반응 본기 경사 회전 목마 애니메이션
51650 단어 reactreactnative
개요
React Native에는
FlatList
구성 요소가 있습니다. 이 구성 요소는 프로젝트 목록을 가져와 목록의 모든 항목에 하나의 요소를 지능적으로 보여줍니다.언뜻 보기에, 이 구성 요소는 단지 대형 원소 목록을 나타내는 데 쓰이는 것 같다.사실이 증명하듯이, React Native FlatList
s는 멋진 일을 많이 할 수 있습니다!이 글에서 우리는 기이한 경사 효과가 있는 회전목마를 구축하는 것 중 하나를 볼 것이다.다음 예제를 참조하십시오.이 예시의 소스 코드 here을 찾을 수 있습니다.
약간의 설정
작은 설정부터 시작합시다.회전 목마 슬라이드를 보여주는 데이터 목록을 만들 것입니다.또한 React Native의
Dimensions
API를 사용하여 화면의 폭과 높이를 얻을 수 있습니다.import { Dimensions } from "react-native";
// Set up our slides
type Slide = {
image: any;
title: string;
subtitle: string;
};
const SLIDES: Slide[] = [
{
image: require("./img/summer.jpg"),
title: "Summer",
subtitle: "Warm days, fun nights.",
},
{
image: require("./img/fall.jpg"),
title: "Fall",
subtitle: "Sweater weather, baby.",
},
{
image: require("./img/winter.jpg"),
title: "Winter",
subtitle: "The season to be jolly.",
},
{
image: require("./img/spring.jpg"),
title: "Spring",
subtitle: "April showers, may flowers.",
},
];
// Utils
const { width, height } = Dimensions.get("window");
회전목마 구축
현재 우리는 이미 데이터 설정을 완성했으니, 우리는 계속 회전목마의 골격을 함께 놓을 것이다.여기에는
FlatList
데이터와 회전목마의 슬라이드를 렌더링하는 사용자 정의 구성 요소 SLIDES
데이터가 포함됩니다.CarouselSlide
의 대상이 회전목마를 포함하는 스타일이 있지만, 지금은 이런 세부 사항을 걱정할 필요가 없다./**
* Tilt Carousel View
*/
export const TiltCarousel: React.FC = () => {
return (
<View style={styles.background}>
<FlatList
data={SLIDES}
renderItem={({ item, index }: { item: Slide; index: number }) => (
<CarouselSlide slide={item} />
)}
horizontal
snapToInterval={width}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
decelerationRate={-1}
bounces={true}
keyExtractor={(slide: Slide) => slide.title}
/>
</View>
);
};
/**
* Slide item
*/
const CarouselSlide: React.FC<{
slide: Slide;
}> = ({ slide }) => {
return (
<View style={styles.cardContainer}>
<ImageBackground source={slide.image} style={{ flex: 1 }}>
<Spacer height={0.7 * height} />
<View style={styles.cardContentContainer}>
<AppText style={styles.title}>{slide.title}</AppText>
<AppText style={styles.subtitle}>{slide.subtitle}</AppText>
</View>
</ImageBackground>
</View>
);
};
여기에는 몇 가지 주의해야 할 점이 있다.styles
의 horizontal
아이템을 사용하여 목록을 수평으로 렌더링할 것입니다.FlatList
을 설정하여 snapToInterval={width}
이 특정 간격으로 포착되도록 합니다.중요한 것은 우리가 FlatList
, 화면의 폭을 포착할 것이다.각 회전목마 슬라이드의 폭도 width
이므로 각 회전목마 슬라이드를 보기에 포착할 수 있습니다.width
과 scrollEventThrottle={16}
을 사용하여 회전목마의 미끄럼 물리를 제어할 것이다.decelerationRate={-1}
은 슬라이드 이미지와 일부 텍스트로만 이미지 배경을 렌더링합니다.사용자 정의 SlideCarousel
및 AppText
구성 요소를 사용하여 텍스트와 공간을 렌더링합니다.그러나 우리는 사용자 정의 애니메이션으로 이 일의 흥미를 높일 것이다.
일부 애니메이션에 뿌리기
우리는 회전목마 슬라이드에 좋은 경사 효과를 줄 것이다. 그들이 보기에 들어가고 떠날 때.그러기 위해서는 다음과 같은 몇 가지 작업이 필요합니다.
Spacer
에서 사용자의 스크롤 위치를 추적합니다.사용자의 스크롤 위치를 추적합니다.
FlatList
스크롤 주위에 애니메이션을 추가하기 위해서는 FlatList
값을 만들고 추적해야 합니다. 이 값은 사용자가 Animated
에서 스크롤하는 거리에 대응합니다.React Native에는 애니메이션 값을 만드는 데 사용할 FlatList
API가 있습니다(애니메이션 값을 설정하고 스타일에서 사용하여 애니메이션 효과를 만들 수 있습니다).우리는 이 애니메이션 값을 사용하여 사용자가 목록에서 얼마나 멀리 굴렀는지 추적할 것이다.이를 위해 Animated.Value
의 onScroll
도구와 FlatList
API를 사용합니다.Animated.event
값을 각 scrollX
요소에 계속 전달하고 전달합니다.export const TiltCarousel: React.FC = () => {
+ const scrollX = React.useRef(new Animated.Value(0)).current;
return (
<View style={styles.background}>
<Animated.FlatList
data={SLIDES}
renderItem={({ item, index }: { item: Slide; index: number }) => (
- <CarouselSlide slide={item} />
+ <CarouselSlide slide={item} scrollX={scrollX} index={index} />
)}
horizontal
snapToInterval={width}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
decelerationRate={-1}
bounces={true}
keyExtractor={(slide: Slide) => slide.title}
+ onScroll={Animated.event(
+ [{ nativeEvent: { contentOffset: { x: scrollX } } }],
+ { useNativeDriver: true },
+ )}
/>
</View>
);
};
const CarouselSlide: React.FC<{
slide: Slide;
+ scrollX: Animated.Value;
+ index: number;
-}> = ({ slide }) => {
+}> = ({ slide, scrollX, index }) => {
이 변경 사항은 시각적 변경 사항을 추가하지 않았지만, 현재 <CarouselSlide />
을 방문하여 사용자의 수평 스크롤 위치를 추적할 수 있습니다. 이 변경 사항을 사용하여 회전 목마 슬라이드의 애니메이션을 설정할 것입니다.회전 목마 슬라이드 애니메이션 설정
우리는 회전목마 슬라이드에 약간의 기울기 효과를 추가할 것이다.
이를 위해
scrollX
의 값(사용자가 scrollX
에서 스크롤하는 거리)과 FlatList
의 값(슬라이드 항목별 인덱스)을 사용합니다.우리는 최종적으로 애니메이션을 만드는 회전목마 슬라이드에 약간의 변환을 적용할 것이다.이제 설정을 좀 해 봅시다.const CarouselSlide: React.FC<{
slide: Slide;
scrollX: Animated.Value;
index: number;
}> = ({ slide, scrollX, index }) => {
// Transforms
const opacity = 1;
const scale = 1;
const perspective = 800;
const translateX = 0;
const rotateY = '0deg';
return (
<Animated.View
style={[
styles.cardContainer,
{
opacity,
transform: [{ scale }, { perspective }, { translateX }, { rotateY }],
},
]}
>
<ImageBackground source={slide.image} style={{ flex: 1 }}>
<Spacer height={0.7 * height} />
<View style={styles.cardContentContainer}>
<AppText style={styles.title}>{slide.title}</AppText>
<AppText style={styles.subtitle}>{slide.subtitle}</AppText>
</View>
</ImageBackground>
</Animated.View>
);
};
위의 코드 세그먼트에서 우리는 index
, opacity
, scale
, perspective
, translateX
과 rotateY
의 기본 값을 설정한 후에 이 값을 우리의 슬라이드 포장기에 응용하였다.우리는 또한 View
을 Animated.View
으로 전환할 것이다. 왜냐하면 우리는 상술한 속성 값을 애니메이션 값으로 전환할 것이다.이제 우리가 애니메이션을 제작할 이러한 속성과 왜 그런지 이야기해 봅시다.
opacity
의 애니메이션을 설정할 것입니다. 이렇게 하면 슬라이드가 보기를 들어가거나 떠날 때'사라지기'효과를 추가할 수 있습니다.scale
의 애니메이션을 설정합니다. 이렇게 하면 슬라이드가 보기를 들어가거나 떠날 때 애니메이션은 축소/증가합니다.perspective
, translateX
및 rotateY
의 애니메이션을 설정하여 슬라이드를 기울게 합니다.카드를 왼쪽으로 미끄러뜨리면 화면 왼쪽을 중심으로 기울어져야 합니다.만약 당신이 오른쪽으로 카드를 미끄러뜨린다면, 그것은 화면의 오른쪽을 둘러싸고 기울어져야 한다.const inputRange = [(index - 1) * width, index * width, (index + 1) * width];
const opacity = scrollX.interpolate({
inputRange,
outputRange: [0, 1, 0],
});
const scale = scrollX.interpolate({
inputRange,
outputRange: [0.6, 1, 0.6],
});
const perspective = scrollX.interpolate({
inputRange,
outputRange: [1200, 800, 1200],
});
const translateX = Animated.subtract(scrollX, index * width);
const rotateY = scrollX.interpolate({
inputRange,
outputRange: ["-45deg", "0deg", "45deg"],
});
이때 기울기 효과가 생성되었습니다!그러나 우리는 우리가 어떻게 이런 애니메이션 값을 구축했는지 되돌아봐야 한다.애니메이션 보간
React 원본 애니메이션 값은
interpolate
방법으로 애니메이션 값을 변환할 수 있습니다.이것은 매우 강력한 도구다!우리는 우리의 scrollX
값을 변환할 것이다.interpolate
방법은 inputRange
과 정의 변환의 outputRange
을 채택한다.우리의 예에서 우리는 이런 줄을 가지고 있다.
const inputRange = [(index - 1) * width, index * width, (index + 1) * width];
우리는 그것을 세 개의 중단점으로 볼 수 있으며, 우리는 그 중에서 각 슬라이드에 비추게 될 것이다.예를 들어, 첫 번째 슬라이드에서는 다음과 같이 생각할 수 있습니다.왼쪽으로 미끄러지면
scrollX
이 index * width
에서 (index - 1) * width
으로 바뀐다.만약 네가 오른쪽으로 미끄러진다면, 그것은 index * width
에서 (index + 1) * width
까지 같지 않을 것이다.따라서 이 inputRange
을 정의된 중단점으로 볼 수 있습니다. 슬라이드가 화면 보기에서 완전히 벗어날 때(왼쪽), 슬라이드가 화면 보기에서 완전히 중간에 있을 때, 그리고 슬라이드가 화면 보기에서 완전히 벗어날 때(오른쪽).그리고 우리는 이러한 중단점을 바탕으로 다른 값을 변환하는 방법을 고려할 수 있다.예를 들어, 슬라이드가 화면 뷰에 없을 때(왼쪽 또는 오른쪽으로)
opacity: 0
을 적용하여 "사라지기"를 원합니다.슬라이드가 화면 보기에 있으면 opacity: 1
이 필요합니다.따라서 opacity
에서 다음과 같은 변환을 통해 scrollX
을 정의할 수 있습니다.const opacity = scrollX.interpolate({
inputRange,
outputRange: [0, 1, 0],
});
이와 유사한 방식으로 슬라이드가 보기에서 벗어날 때 약간 수축되기를 원하기 때문에 우리는 다음과 같이 정의할 수 있다.const scale = scrollX.interpolate({
inputRange,
outputRange: [0.6, 1, 0.6],
});
우리는 이렇게 생각할 수 있다.scale: 0.6
. scale: 1
. scale: 0.6
. 경사변환
이제 다음 항목만 남았습니다.
const perspective = scrollX.interpolate({
inputRange,
outputRange: [1200, 800, 1200],
});
const translateX = Animated.subtract(scrollX, index * width);
const rotateY = scrollX.interpolate({
inputRange,
outputRange: ["-45deg", "0deg", "45deg"],
});
나는 이런 무료한 세부 사항을 토론하고 싶지 않지만, 화면 가장자리에서'경사'효과를 만들려면, 우리는 세 가지 연속적인 변환 (그리고 순서!) 을 실행해야 한다.고위층에서 볼 때 우리는 다음과 같은 방식으로 이러한 전환을 고려할 수 있다.perspective
을 사용하여 슬라이드를 화면에서 이동할 때 사용자가 밀어내는 것처럼 보입니다.translateX
을 사용하여 슬라이더를 왼쪽/오른쪽으로 이동하여 기울기의 회전축을 결정합니다.rotateY
을 사용하여 회전 효과를 생성합니다.결론
전체 "경사"효과는 복잡한 수학/변환이 있지만, 이러한 변환 설정이 도움이 되고 도구를 제공하여 React Native
FlatList
s를 바탕으로 자신의 기이한 애니메이션을 만들기 시작합니다!전면적으로 보기 위해 다음은 모든 코드입니다.import * as React from "react";
import {
Animated,
Dimensions,
ImageBackground,
StyleSheet,
View,
} from "react-native";
import { AppText } from "../../components/AppText";
import { Spacer } from "../../components/Spacer";
// Set up our slides
type Slide = {
image: any;
title: string;
subtitle: string;
};
const SLIDES: Slide[] = [
{
image: require("./img/summer.jpg"),
title: "Summer",
subtitle: "Warm days, fun nights.",
},
{
image: require("./img/fall.jpg"),
title: "Fall",
subtitle: "Sweater weather, baby.",
},
{
image: require("./img/winter.jpg"),
title: "Winter",
subtitle: "The season to be jolly.",
},
{
image: require("./img/spring.jpg"),
title: "Spring",
subtitle: "April showers, may flowers.",
},
];
// Utils
const { width, height } = Dimensions.get("window");
/**
* Tilt Carousel View
*/
export const TiltCarousel: React.FC = () => {
const scrollX = React.useRef(new Animated.Value(0)).current;
return (
<View style={styles.background}>
<Animated.FlatList
data={SLIDES}
renderItem={({ item, index }: { item: Slide; index: number }) => (
<CarouselSlide slide={item} scrollX={scrollX} index={index} />
)}
horizontal
snapToInterval={width}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
decelerationRate={-1}
bounces={true}
keyExtractor={(slide: Slide) => slide.title}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { x: scrollX } } }],
{ useNativeDriver: true },
)}
/>
</View>
);
};
/**
* Slide item
*/
const CarouselSlide: React.FC<{
slide: Slide;
scrollX: Animated.Value;
index: number;
}> = ({ slide, scrollX, index }) => {
const inputRange = [(index - 1) * width, index * width, (index + 1) * width];
const opacity = scrollX.interpolate({
inputRange,
outputRange: [0, 1, 0],
});
const scale = scrollX.interpolate({
inputRange,
outputRange: [0.6, 1, 0.6],
});
const perspective = scrollX.interpolate({
inputRange,
outputRange: [1200, 800, 1200],
});
const translateX = Animated.subtract(scrollX, index * width);
const rotateY = scrollX.interpolate({
inputRange,
outputRange: ["-45deg", "0deg", "45deg"],
});
return (
<Animated.View
style={[
styles.cardContainer,
{
opacity,
transform: [{ scale }, { perspective }, { translateX }, { rotateY }],
},
]}
>
<ImageBackground source={slide.image} style={{ flex: 1 }}>
<Spacer height={0.7 * height} />
<View style={styles.cardContentContainer}>
<AppText style={styles.title}>{slide.title}</AppText>
<AppText style={styles.subtitle}>{slide.subtitle}</AppText>
</View>
</ImageBackground>
</Animated.View>
);
};
/**
* Styling
*/
const styles = StyleSheet.create({
background: { flex: 1, backgroundColor: "rgba(30,30,30,0.8)" },
cardContainer: {
width,
flex: 1,
justifyContent: "center",
borderRadius: 30,
overflow: "hidden",
},
cardContentContainer: {
alignItems: "center",
backgroundColor: "rgba(0,0,0,0.3)",
padding: 16,
},
title: {
color: "white",
fontWeight: "bold",
fontSize: 64,
textShadowColor: "black",
textShadowRadius: 4,
textShadowOffset: {
width: 1,
height: 1,
},
},
subtitle: {
color: "rgb(230,230,230)",
fontWeight: "600",
fontSize: 18,
},
});
Reference
이 문제에 관하여(반응 본기 경사 회전 목마 애니메이션), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gksander/react-native-tilt-carousel-animation-13ep텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)