Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9328

子供用の学習アプリケーションを作る(2) アニメーション編

$
0
0

はじめに

以前作成したアプリの続きをしていきます。
参考: 子供用の学習アプリケーションを作る(1)

今回は、コンテンツの選択画面にアニメーションを導入し、選択後の詳細画面を作成したので、その実装について記事にしていこうと思います。

動作

まずは、動作を見ていただければと思います。

test3.gif

実装

構成

構成は以下のようになっています。

❯ pwd        
/Users/yoshitaka.koitabashi/Desktop/iLearn/src/components

~/Desktop/iLearn/src/components
❯ tree .             
.
├── alsContent.tsx
├── contentsSelect.tsx
├── falcon9Content.tsx
├── header.tsx
└── spaceContent.tsx

0 directories, 5 files

今回の実装の説明に使用するのは、こちらです。
・contentsSelect.tsx
コンテンツを選択する画面

Home画面からの遷移時に、各コンテンツがふんわり浮かび上がるアニメーションを作成しました。
参考 react-native: Animated
こちらの実装なのですが、単純で、Animatedというライブラリと副作用fookであるuseEffectを利用したパターンになります。

contentsSelect.tsx
import'react-native-gesture-handler';importReact,{useRef,useEffect}from'react';import{SafeAreaView,ScrollView,StyleSheet,Animated,TouchableOpacity,}from'react-native';import{Card,Title}from'react-native-paper';import{createStackNavigator}from'@react-navigation/stack';importAppHeaderfrom'./header';importspaceContentfrom'./spaceContent';importalsContentsfrom'./alsContent';importfalcon9Contentsfrom'./falcon9Content';constcontents=({navigation})=>{constfadeSpace=useRef(newAnimated.Value(0)).current;constfadeAls=useRef(newAnimated.Value(0)).current;constfadeFalcon9=useRef(newAnimated.Value(0)).current;constspaceContentFadeIn=()=>{Animated.timing(fadeSpace,{toValue:1,duration:500,useNativeDriver:true,}).start();};constalsContentsFadeIn=()=>{Animated.timing(fadeAls,{toValue:1,duration:2000,useNativeDriver:true,}).start();};constfalcon9ContentsFadeIn=()=>{Animated.timing(fadeFalcon9,{toValue:1,duration:3000,useNativeDriver:true,}).start();};useEffect(()=>{spaceContentFadeIn();alsContentsFadeIn();falcon9ContentsFadeIn();});return(<SafeAreaViewstyle={styles.container}><ScrollViewcontentContainerStyle={styles.contentContainer}><TouchableOpacityonPress={()=>{navigation.navigate('Home');}}><AppHeader/></TouchableOpacity>
<Animated.Viewstyle={[{opacity:fadeSpace}]}><CardonPress={()=>navigation.navigate('宇宙って?')}style={styles.cardPadding}><Card.Content><Titlestyle={styles.cardTitle}>宇宙って</Title>
<Card.Coversource={require('../../public/img/alien.png')}style={styles.cardImg}/>
</Card.Content>
</Card>
</Animated.View>
<Animated.Viewstyle={[{opacity:fadeAls}]}><CardonPress={()=>navigation.navigate('ALSって知ってる?')}style={styles.cardPadding}><Card.Content><Titlestyle={styles.cardTitle}>ALSって知ってる</Title>
<Card.Coversource={require('../../public/img/health.png')}style={styles.cardImg}/>
</Card.Content>
</Card>
</Animated.View>
<Animated.Viewstyle={[{opacity:fadeFalcon9}]}><CardonPress={()=>navigation.navigate('Falcon9がすごい')}style={styles.cardPadding}><Card.Content><Titlestyle={styles.cardTitle}>Falcon9がすごい</Title>
<Card.Coversource={require('../../public/img/startup_isometric.png')}style={styles.cardImg}/>
</Card.Content>
</Card>
</Animated.View>
</ScrollView>
</SafeAreaView>
);};constStack=createStackNavigator();constcontentsSelect=()=>(<Stack.Navigator><Stack.Screenname="知識の森"component={contents}/>
<Stack.Screenname="宇宙って?"component={spaceContent}/>
<Stack.Screenname="ALSって知ってる?"component={alsContents}/>
<Stack.Screenname="Falcon9がすごい"component={falcon9Contents}/>
</Stack.Navigator>
);conststyles=StyleSheet.create({container:{flex:1,},cardImg:{height:300,},cardPadding:{top:60,marginBottom:20,borderRadius:5,marginLeft:20,marginRight:20,},cardTitle:{fontWeight:'bold',},contentContainer:{paddingBottom:50,},});exportdefaultcontentsSelect;

・spaceContent.tsx
宇宙についてのコンテンツの詳細画面

詳細画面で少し面白い箇所が、下記です。
何をしているかというと、Home画面に戻す動作をしているのですが、dispatch(StackActions.popToTop())をしないと、navigationのHistoryが消されず想定外の動作をしてしまいます。

navigation.navigate('Home');
navigation.dispatch(StackActions.popToTop());
spaceContent.tsx
import*asReactfrom'react';import{ScrollView,StyleSheet,View,Image,TouchableOpacity,}from'react-native';import{Card,Paragraph,Chip,Avatar,Title,}from'react-native-paper';import{StackActions}from'@react-navigation/native';import{Text}from'react-native-elements';importAppHeaderfrom'./header';constspaceContent=({navigation})=>(<Viewstyle={styles.container}><ScrollViewcontentContainerStyle={styles.contentContainer}><TouchableOpacityonPress={()=>{navigation.navigate('Home');navigation.dispatch(StackActions.popToTop());}}><AppHeader/></TouchableOpacity>
<Cardstyle={styles.cardPadding}><Card.Content><Titlestyle={styles.cardTitle}>宇宙ってなんだろう??</Title>
<Card.Coversource={require('../../public/img/alien.png')}/>
</Card.Content>
</Card>
<Cardstyle={styles.cardPadding}><Card.Content><Paragraphstyle={styles.nextCardMessage}>Topics</Paragraph>
<Viewstyle={styles.row}><Chipstyle={styles.chip}><Textstyle={styles.chipText}>宇宙開発</Text>
</Chip>
<Chipstyle={styles.chip}><Textstyle={styles.chipText}>Jaxa</Text>
</Chip>
<Chipstyle={styles.chip}><Textstyle={styles.chipText}>ISS</Text>
</Chip>
</View>
</Card.Content>
</Card>
<Cardstyle={styles.cardPadding}><Card.Content><Paragraphstyle={styles.nextCardMessage}>作者</Paragraph>
<Viewstyle={styles.row}><Avatar.Imagesize={70}source={require('../../public/img/space-travel.png')}/>
<Textstyle={styles.avatarMessage}>KoitabashiYoshitaka</Text>
</View>
</Card.Content>
</Card>
<Cardstyle={styles.cardPadding}><Card.Content><Paragraphstyle={styles.nextCardMessage}>物語</Paragraph>
<Texth3style={styles.storyTitle}>はじめに</Text>
<Textstyle={styles.storyBody}>宇宙の誕生は約138億年前のビッグバンから始まります</Text>
<Imagesource={require('../../public/img/moon2.png')}style={{width:300,height:200}}/>
<Texth4style={styles.storyTitle}>ビックバンって〜?</Text>
<Textstyle={styles.storyBody}>人間のまばたきよりも短い時間の中で起こった超高エネルギーの爆発ビックバンですビッグバンにより小さな物質同士が結合し合い星の素となるチリやガスが生まれました{'\n'}さらにそれらの物質がくっつき合い恒星や惑星といった星々が生まれたのです{'\n'}</Text>
<Imagesource={require('../../public/img/moon1.png')}style={{width:300,height:200}}/>
<Textstyle={styles.storyBody}>誕生以来宇宙は膨張を続けておりその膨張は加速し続けているといわれています{'\n'}そのため宇宙の大きさは現在の科学でも解明できていません</Text>
</Card.Content>
</Card>
</ScrollView>
</View>
);conststyles=StyleSheet.create({container:{flex:1,},backButton:{paddingTop:10,paddingBottom:10,},cardPadding:{textAlign:'center',top:60,marginBottom:20,borderRadius:5,marginLeft:20,marginRight:20,},cardTitle:{marginBottom:15,fontSize:20,fontWeight:'bold',},cardMessage:{marginTop:15,fontSize:20,fontWeight:'bold',},nextCardMessage:{marginBottom:20,fontSize:20,fontWeight:'bold',},row:{flexDirection:'row',flexWrap:'wrap',paddingHorizontal:12,},chip:{backgroundColor:'#2096F3',margin:2,},chipText:{color:'#ffffff',},avatarMessage:{marginLeft:30,marginTop:20,fontWeight:'bold',textAlign:'left',},storyTitle:{marginTop:20,marginBottom:20,fontWeight:'bold',},storyBody:{marginTop:20,fontWeight:'bold',},contentContainer:{paddingBottom:60,},});exportdefaultspaceContent;

おわり

・ 説明が雑になってきているので、だんだん追記していきます。w
・ 現在は、各コンテンツの内容をハードコーディングしているのですが、いずれ専用のAPIを作成するつもりなので、そこはとりあえず置いておきます。
・ あとは、Qittaのようにmarkdownで誰でも編集できるようにしていきたいと思ってます。

参考文献

宇宙について親子で楽しく学ぼう


Viewing all articles
Browse latest Browse all 9328

Trending Articles