Skip to content

Instantly share code, notes, and snippets.

@35d
Created November 9, 2018 09:45
Show Gist options
  • Save 35d/2c5da3b59380f74ff342300cf7da6d68 to your computer and use it in GitHub Desktop.
Save 35d/2c5da3b59380f74ff342300cf7da6d68 to your computer and use it in GitHub Desktop.
React Native Card Animation
// @flow
import React, { Component } from 'react';
import {
TouchableWithoutFeedback,
Animated,
Dimensions,
StyleSheet,
} from 'react-native';
type Props = {
style?: Object,
children: React.Node,
onPress?: Function,
};
type State = {
sizeRatio: Animated,
};
const styles = StyleSheet.create({
card: {
backgroundColor: '#FFF',
width: Dimensions.get('window').width - 32,
borderRadius: 16,
borderWidth: 0,
shadowColor: '#03091d',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 1.0,
shadowRadius: 20,
},
});
export default class Card extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
sizeRatio: new Animated.Value(1),
};
}
render() {
return (
<TouchableWithoutFeedback
onPressIn={() => {
Animated.spring(this.state.sizeRatio, {
toValue: 0.94,
friction: 4, // 摩擦 (大きい方が振動が減衰しやすい)
tension: 36, // ばね定数
useNativeDriver: true,
}).start();
}}
onPress={
// なんか処理する
this.props.onPress
}
onPressOut={() => {
Animated.spring(this.state.sizeRatio, {
toValue: 1,
friction: 4, // 摩擦 (大きい方が振動が減衰しやすい)
tension: 36, // ばね定数
}).start();
}}
>
<Animated.View
style={[
styles.card,
this.props.style,
{
transform: [{ scale: this.state.sizeRatio }],
},
]}
>
{this.props.children}
</Animated.View>
</TouchableWithoutFeedback>
);
}
}
Card.defaultProps = {
style: {},
onPress: () => {}, // デフォルト何もしない
};
// @flow
import React, { Component } from 'react';
import { Image, ScrollView, StyleSheet, View, Text } from 'react-native';
import Card from './Component/Atoms/Card';
const IMAGE_1 =
'https://images.unsplash.com/photo-1539783559030-94d253662acd?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=dc2790e76eddcb04d43e7c47b489c735&auto=format&fit=crop&w=1300&q=80';
const IMAGE_2 =
'https://images.unsplash.com/photo-1539553296722-f41aa0d2d184?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1ea590d8dd6c9247b9a2d2237b198d5f&auto=format&fit=crop&w=934&q=80';
const IMAGE_3 =
'https://images.unsplash.com/photo-1539765398826-caf9e08732c5?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=c8680afeec51fa57b02d8f9b11ee50dd&auto=format&fit=crop&w=934&q=80';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#091332',
},
cardBodyArea: {
padding: 16,
},
titleText: {
fontSize: 20,
fontWeight: '800',
color: '#007aff',
},
bodyText: {
fontWeight: '400',
},
footerText: {
fontWeight: '400',
color: 'gray',
},
});
export default class CardInteraction extends Component {
componentDidMount() {}
renderCards = () => (
<View style={{ alignItems: 'center' }}>
<Card
style={{ marginBottom: 64 }}
onPress={() => {
// alert('関数を渡す場合');
}}
>
<View
style={{
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
overflow: 'hidden',
}}
>
<Image
style={{
width: '100%',
height: 120,
}}
source={{ uri: IMAGE_1 }}
/>
<View style={styles.cardBodyArea}>
<Text style={[styles.titleText, { marginBottom: 4 }]}>Title</Text>
<Text style={[styles.bodyText, { marginBottom: 4 }]}>
This is card component sample.
</Text>
<Text style={[styles.footerText, { marginBottom: 4 }]}>sample</Text>
</View>
</View>
</Card>
</View>
);
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.innerContent}>{this.renderCards()}</View>
</ScrollView>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment