react-native实现类似贝壳找房的一个卡片翻转的效果。
实现效果就是如下图所示
实现的demo如下
import React, {Component, useState, useRef, useEffect} from 'react';
import {
StyleSheet,
SafeAreaView,
Text,
Image,
View,
Easing,
TouchableOpacity,
Animated,
} from 'react-native';
// 翻转卡片动画demo
const info = {
cardType: 'front', // back
text: '2室1厅/62.39m²',
name: '12人关注此房',
price: 415,
url:
'https://ke-image.ljcdn.com/110000-inspection/pc1_POwFMVR8O.jpg!m_fill,w_210,h_164,f_jpg?from=ke.com',
};
const Interpolate = () => {
let timer = null;
let rotateAnimatedRef = useRef(null);
const [animatedValue, setAnimatedValue] = useState(new Animated.Value(0));
const [cardInfo, setCardInfo] = useState(info);
useEffect(() => {
initAnimated();
return () => {
timer && clearTimeout(timer);
};
}, []);
// 初始化的广告数据
const initAnimated = () => {
rotateAnimatedRef.current = Animated.timing(animatedValue, {
useNativeDriver: true, // 启用原声动画
toValue: 1,
duration: 800,
easing: Easing.in,
perspective: 2000,
});
rotateAnimatedRef.current.start();
};
const _startAnimated = () => {
timer = setTimeout(
() => {
if (cardInfo.cardType === 'front') {
setCardInfo(info);
} else {
setCardInfo({
color: 'red',
text: '2室1厅/62.39m²',
name: '12人关注此房',
price: 415,
url:
'https://ke-image.ljcdn.com/110000-inspection/pc1_POwFMVR8O.jpg!m_fill,w_210,h_164,f_jpg?from=ke.com',
});
}
}, //延时操作
350, //延时时间
);
animatedValue.setValue(0);
rotateAnimatedRef.current.start();
};
const rotateY = animatedValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: ['0deg', '90deg', '0deg'],
});
return (
<SafeAreaView style={styles.mainStyle}>
<Animated.View
style={{
alignSelf: 'center',
width: 105,
height: 180,
// justifyContent: 'center',
// alignItems: 'center',
fontSize: 18,
backgroundColor: '#ffffff',
paddingBottom: 20,
shadowColor: '#ccc',
shadowOffset: {
width: 1,
height: -1,
},
shadowOpacity: 0.5,
shadowRadius: 1,
transform: [{rotateY: rotateY}],
}}>
<Image style={{width: 105, height: 80}} source={{uri: cardInfo.url}} />
<View style={{marginTop: 8, paddingLeft: 4}}>
<Text style={{fontSize: 12, color: '#000'}}>{cardInfo.text}</Text>
</View>
<View style={{marginTop: 8, paddingLeft: 4}}>
<Text style={{fontSize: 12, color: '#000'}}>{cardInfo.name}</Text>
</View>
<View style={{marginTop: 8, paddingLeft: 4}}>
<Text style={{fontSize: 12, color: 'red'}}>{cardInfo.price}万</Text>
</View>
</Animated.View>
<TouchableOpacity style={styles.touchStyle} onPress={_startAnimated}>
<Text
style={{
width: 200,
height: 100,
textAlign: 'center',
lineHeight: 100,
}}>
点击开始动画
</Text>
</TouchableOpacity>
</SafeAreaView>
);
};
export default Interpolate;
const styles = StyleSheet.create({
mainStyle: {
flex: 1,
backgroundColor: '#eee',
},
touchStyle: {
padding: 10,
alignSelf: 'flex-end',
},
});
代码的实现效果