React Native SVG Animation 不会为最后一个数组项设置动画
React Native SVG Animation doesn't animate the last array item
我是 React Native Animation 的新手,我正在学习教程,我完全按照他所教的去做,但我没有得到想要的结果。我正在尝试开发一个带有 svg 动画的多页入职屏幕。问题是它工作正常,但是当我到达平面列表中的最后一项时,它不会更新索引,因此最后一个数组项的动画没有完成。
相关代码如下:
注册屏幕:
const data = [
<EmailComponent />,
<PasswordComponent />,
<DPComponent />,
<AgeComponent />,
];
const RegisterScreen = () => {
const scrollX = useRef(new Animated.Value(0)).current;
const [currentIndex, setCurrentIndex] = useState(0);
const slidesRef = useRef(null);
const viewableItemsChanged = useCallback(({viewableItems}) => {
console.log(viewableItems[0]);
setCurrentIndex(viewableItems[0].index);
}, []);
const scrollTo = () => {
if (currentIndex < data.length - 1) {
slidesRef.current.scrollToIndex({index: currentIndex + 1});
} else {
console.log('Last Item!');
}
};
const goBack = () => {
if (currentIndex === 0) {
return;
}
slidesRef.current.scrollToIndex({index: currentIndex - 1});
};
// console.log(currentIndex);
return (
<RegisterationStateProvider>
<View style={styles.container}>
<StatusBar barStyle="dark-content" backgroundColor="#ffffff" />
<SafeAreaView style={styles.back}>
<TouchableOpacity onPress={goBack} activeOpacity={0.6}>
<AntDesign name="arrowleft" size={32} color="black" />
</TouchableOpacity>
</SafeAreaView>
<View style={{flex: 3}}>
<FlatList
ref={slidesRef}
scrollEnabled
data={data}
keyExtractor={(_, index) => 'key' + index}
renderItem={({item}) => item}
horizontal
showsHorizontalScrollIndicator={false}
pagingEnabled
bounces={false}
onScroll={
Animated.event(
[{nativeEvent: {contentOffset: {x: scrollX}}}],
{useNativeDriver: false},
)}
scrollEventThrottle={32}
onViewableItemsChanged={viewableItemsChanged}
/>
</View>
<Dot data={data} scrollX={scrollX} />
<NextButton
scrollTo={scrollTo}
percentage={(currentIndex + 1) * (100 / data.length)}
/>
</View>
</RegisterationStateProvider>
);
};
下一个按钮:
const NextButton = ({percentage, scrollTo}) => {
const size = 100;
const strokeWidth = 4;
const center = size / 2;
const radius = size / 2 - strokeWidth / 2;
const circumference = 2 * Math.PI * radius;
// console.log(percentage);
const progressAnimation = useRef(new Animated.Value(0)).current;
const progressRef = useRef(null);
const animation = toValue => {
return Animated.timing(progressAnimation, {
toValue,
duration: 250,
useNativeDriver: false,
}).start();
};
useEffect(() => {
animation(percentage);
}, [percentage]);
useEffect(() => {
progressAnimation.addListener(
value => {
const strokeDashoffset =
circumference - (circumference * value.value) / 100;
if (progressRef?.current) {
progressRef.current.setNativeProps({
strokeDashoffset,
});
}
},
[percentage],
);
return () => {
progressAnimation.removeAllListeners();
};
}, []);
return (
<View style={styles.container}>
<Svg width={size} height={size}>
<G rotation="-90" origin={center}>
<Circle
stroke="#E6E7E8"
cx={center}
cy={center}
r={radius}
strokeWidth={strokeWidth}
/>
<Circle
ref={progressRef}
stroke="#FF5864"
cx={center}
cy={center}
r={radius}
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={circumference}
/>
</G>
</Svg>
<TouchableOpacity
disabled={false}
onPress={scrollTo}
style={styles.button}
>
<AntDesign name="arrowright" size={35} color="#fff" />
</TouchableOpacity>
</View>
);
};
我在代码中找不到 error/bug,一切看起来都很好,因为当我在 scrollTo
函数中检查 if (currentIndex < data.length - 1)
时,它应该呈现 index=3 因为 3<4
显然是真的,但不幸的是它不起作用,控制台也没有错误。
下面是 console.log(currentIndex);
& console.log(percentage);
的控制台输出
LOG {"index": 0, "isViewable": true, "item": <EmailComponent />, "key": "key0"}
LOG {"index": 0, "isViewable": true, "item": <EmailComponent />, "key": "key0"}
LOG {"index": 1, "isViewable": true, "item": <PasswordComponent />, "key": "key1"}
LOG {"index": 1, "isViewable": true, "item": <PasswordComponent />, "key": "key1"}
LOG {"index": 2, "isViewable": true, "item": <DPComponent />, "key": "key2"}
LOG 0
LOG 25
LOG 1
LOG 50
LOG 2
LOG 75
如您所见,即使我在最后一项,动画仍处于 (75%) 270° 且未完全完成,即 (100%) 360° 且 {index:3} 未记录在控制台中,即使我是最后一项数据。
FlatList 中的最后一项未触发 onViewableItemsChanged
。降低viewAreaCoveragePercentThreshold
中的viewabilityConfig
属性https://reactnative.dev/docs/flatlist#viewabilityconfig
我是 React Native Animation 的新手,我正在学习教程,我完全按照他所教的去做,但我没有得到想要的结果。我正在尝试开发一个带有 svg 动画的多页入职屏幕。问题是它工作正常,但是当我到达平面列表中的最后一项时,它不会更新索引,因此最后一个数组项的动画没有完成。
相关代码如下:
注册屏幕:
const data = [
<EmailComponent />,
<PasswordComponent />,
<DPComponent />,
<AgeComponent />,
];
const RegisterScreen = () => {
const scrollX = useRef(new Animated.Value(0)).current;
const [currentIndex, setCurrentIndex] = useState(0);
const slidesRef = useRef(null);
const viewableItemsChanged = useCallback(({viewableItems}) => {
console.log(viewableItems[0]);
setCurrentIndex(viewableItems[0].index);
}, []);
const scrollTo = () => {
if (currentIndex < data.length - 1) {
slidesRef.current.scrollToIndex({index: currentIndex + 1});
} else {
console.log('Last Item!');
}
};
const goBack = () => {
if (currentIndex === 0) {
return;
}
slidesRef.current.scrollToIndex({index: currentIndex - 1});
};
// console.log(currentIndex);
return (
<RegisterationStateProvider>
<View style={styles.container}>
<StatusBar barStyle="dark-content" backgroundColor="#ffffff" />
<SafeAreaView style={styles.back}>
<TouchableOpacity onPress={goBack} activeOpacity={0.6}>
<AntDesign name="arrowleft" size={32} color="black" />
</TouchableOpacity>
</SafeAreaView>
<View style={{flex: 3}}>
<FlatList
ref={slidesRef}
scrollEnabled
data={data}
keyExtractor={(_, index) => 'key' + index}
renderItem={({item}) => item}
horizontal
showsHorizontalScrollIndicator={false}
pagingEnabled
bounces={false}
onScroll={
Animated.event(
[{nativeEvent: {contentOffset: {x: scrollX}}}],
{useNativeDriver: false},
)}
scrollEventThrottle={32}
onViewableItemsChanged={viewableItemsChanged}
/>
</View>
<Dot data={data} scrollX={scrollX} />
<NextButton
scrollTo={scrollTo}
percentage={(currentIndex + 1) * (100 / data.length)}
/>
</View>
</RegisterationStateProvider>
);
};
下一个按钮:
const NextButton = ({percentage, scrollTo}) => {
const size = 100;
const strokeWidth = 4;
const center = size / 2;
const radius = size / 2 - strokeWidth / 2;
const circumference = 2 * Math.PI * radius;
// console.log(percentage);
const progressAnimation = useRef(new Animated.Value(0)).current;
const progressRef = useRef(null);
const animation = toValue => {
return Animated.timing(progressAnimation, {
toValue,
duration: 250,
useNativeDriver: false,
}).start();
};
useEffect(() => {
animation(percentage);
}, [percentage]);
useEffect(() => {
progressAnimation.addListener(
value => {
const strokeDashoffset =
circumference - (circumference * value.value) / 100;
if (progressRef?.current) {
progressRef.current.setNativeProps({
strokeDashoffset,
});
}
},
[percentage],
);
return () => {
progressAnimation.removeAllListeners();
};
}, []);
return (
<View style={styles.container}>
<Svg width={size} height={size}>
<G rotation="-90" origin={center}>
<Circle
stroke="#E6E7E8"
cx={center}
cy={center}
r={radius}
strokeWidth={strokeWidth}
/>
<Circle
ref={progressRef}
stroke="#FF5864"
cx={center}
cy={center}
r={radius}
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={circumference}
/>
</G>
</Svg>
<TouchableOpacity
disabled={false}
onPress={scrollTo}
style={styles.button}
>
<AntDesign name="arrowright" size={35} color="#fff" />
</TouchableOpacity>
</View>
);
};
我在代码中找不到 error/bug,一切看起来都很好,因为当我在 scrollTo
函数中检查 if (currentIndex < data.length - 1)
时,它应该呈现 index=3 因为 3<4
显然是真的,但不幸的是它不起作用,控制台也没有错误。
下面是 console.log(currentIndex);
& console.log(percentage);
LOG {"index": 0, "isViewable": true, "item": <EmailComponent />, "key": "key0"}
LOG {"index": 0, "isViewable": true, "item": <EmailComponent />, "key": "key0"}
LOG {"index": 1, "isViewable": true, "item": <PasswordComponent />, "key": "key1"}
LOG {"index": 1, "isViewable": true, "item": <PasswordComponent />, "key": "key1"}
LOG {"index": 2, "isViewable": true, "item": <DPComponent />, "key": "key2"}
LOG 0
LOG 25
LOG 1
LOG 50
LOG 2
LOG 75
如您所见,即使我在最后一项,动画仍处于 (75%) 270° 且未完全完成,即 (100%) 360° 且 {index:3} 未记录在控制台中,即使我是最后一项数据。
onViewableItemsChanged
。降低viewAreaCoveragePercentThreshold
中的viewabilityConfig
属性https://reactnative.dev/docs/flatlist#viewabilityconfig