é»éåœéæ
å ±ãµãŒãã¹ ããªãŒãã³ ã€ãããŒã·ã§ã³ ã©ãã® æ¯å康é ã§ãã ä»åã¯ã Expoã®å
¬åŒãã¥ãŒããªã¢ã« ããã£ãŠãããããšæããŸãã ãããžã§ã¯ãã®äœæ Download assets Install dependencies ã¢ããªã®å®è¡ ã³ãŒãã®ç·šé ããã¹ãã®æåè²ã®å€æŽ ã€ã¡ãŒãžã®è¡šç€º ImageViewerã³ã³ããŒãã³ã Buttonã³ã³ããŒãã³ã PhotoButtonã³ã³ããŒãã³ã ç»åã®éžæ ãŸãšã 仲éåé ãããžã§ã¯ãã®äœæ StickerSmash ãããžã§ã¯ããäœæããŸãããã npx create-expo-app StickerSmash && cd StickerSmash Download assets https://docs.expo.dev/static/images/tutorial/sticker-smash-assets.zip ãããŠã³ããŒãããŠããè§£åããStickerSmash/assetsã«æ ŒçŽããŸããæ¢åã®ãã¡ã€ã«ã¯çœ®ãæããŠãã ããã Install dependencies Webã§ãå®è¡ã§ããããã«ããããã«ãå¿
èŠãªã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ããŸãã npx expo install react-dom react-native-web @expo/webpack-config ã¢ããªã®å®è¡ ãããžã§ã¯ãã® ãã£ã¬ã¯ã ãªã§ã npx expo start ãå®è¡ããŸãã wãæŒããšãWebã¢ããªã詊ãããšãã§ããŸãã æ¬¡ã®ããã«è¡šç€ºãããŸããã ã³ãŒãã®ç·šé ãããžã§ã¯ãã® ãã£ã¬ã¯ã ãªã§ã code . ãå®è¡ããŠã VS Code ãç«ã¡äžããŸãã èæ¯ã #25292e ã«å€æŽããŸãããã const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#25292e", alignItems: "center", justifyContent: "center", }, }); 次ã®ããã«è¡šç€ºãããŸããã ããã¹ãã®ããã©ã«ãã®æåè²ã¯é»ãªã®ã§ãèæ¯ãé»ã£ãœããªã£ãããšã§ãæåãèŠãèŸããªã£ãŠããŸããŸããã ããã¹ãã®æåè²ã®å€æŽ Textã¿ã°ã®style屿§ã§ãæåã®è²ãçœã«æå®ããŸãããã <Text style={{ color: "#fff" }}> Open up App.js to start working on your app! </Text> 次ã®ããã«è¡šç€ºãããŸããã ã€ã¡ãŒãžã®è¡šç€º ã€ã¡ãŒãžã衚瀺ããŸãããã Image ã³ã³ããŒãã³ã ãã€ã³ããŒãããŸãã import { StyleSheet, View, Image } from 'react-native'; 次ã¯ãã€ã¡ãŒãžãã¹ã®èšå®ã§ãã const PlaceholderImage = require('./assets/images/background-image.png'); Imageã¿ã°ã䜿ãåã«ã ã¹ã¿ã€ã«ã·ãŒã ã®èšå®ãããŸãããã const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#25292e", alignItems: "center", }, imageContainer: { flex: 1, paddingTop: 58, }, image: { width: 320, height: 440, borderRadius: 18, }, }); æºåãã§ããã®ã§ãImage ã³ã³ããŒãã³ã ã䜿ã£ãŠã¿ãŸãããã <View style={styles.imageContainer}> <Image source={PlaceholderImage} style={styles.image} /> </View> äžèšã®ããã«è¡šç€ºãããŸããã ImageViewer ã³ã³ããŒãã³ã å
ã»ã©äœã£ãã€ã¡ãŒãžè¡šç€ºæ©èœã ã³ã³ããŒãã³ã åããŸãããã StickSmash ãã£ã¬ã¯ã ãªã®äžã«components ãã£ã¬ã¯ã ãªãäœæããŸãã .../StickerSmash$ mkdir components VS Code ã§ ImageViewer.js ãäœæããŸãã code components/ImageViewer.js äžèšã®ã³ãŒãã ImageViewer.js ã«æžã蟌ã¿ãŸãã import { StyleSheet, Image } from 'react-native'; export default function ImageViewer({ placeholderImageSource }) { return ( <Image source={placeholderImageSource} style={styles.image} /> ); } const styles = StyleSheet.create({ image: { width: 320, height: 440, borderRadius: 18, }, }); App.js ãã ImageViewer.js ãåŒã³åºããŸãã import ImageViewer from './components/ImageViewer'; const PlaceholderImage = require('./assets/images/background-image.png'); export default function App() { return ( <View style={styles.container}> <View style={styles.imageContainer}> <ImageViewer placeholderImageSource={PlaceholderImage} /> </View> <StatusBar style="auto" /> </View> ); } èŠãç®ã¯ãã¡ãã以åãšäžç·ã§ãã Button ã³ã³ããŒãã³ã ãããããã¿ã³ã2ã€äœããŸããããã®åã«ãButton ã³ã³ããŒãã³ã ãäœã£ãŠãããå©çšããããšã«ããŸãããã VS Code ã§ Button.js ãäœæããŸãã code components/Button.js äžèšã®ã³ãŒãã Button.js ã«æžã蟌ã¿ãŸãã import { StyleSheet, View, Pressable, Text } from 'react-native'; export default function Button({ label }) { return ( <View style={styles.buttonContainer}> <Pressable style={styles.button} onPress={() => alert('You pressed a button.')}> <Text style={styles.buttonLabel}>{label}</Text> </Pressable> </View> ); } const styles = StyleSheet.create({ buttonContainer: { width: 320, height: 68, marginHorizontal: 20, alignItems: 'center', justifyContent: 'center', padding: 3, }, button: { borderRadius: 10, width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', flexDirection: 'row', }, buttonLabel: { color: '#fff', fontSize: 16, }, }); App.js ãã Button.js ãåŒã³åºããŸãã import Button from './components/Button'; <View style={styles.footerContainer}> <Button label="Choose a photo" /> <Button label="Use this photo" /> </View> const styles = StyleSheet.create({ // Styles that are unchanged from previous step are hidden for brevity. footerContainer: { flex: 1 / 3, alignItems: 'center', }, }); äžèšã®ããã«è¡šç€ºãããŸããã PhotoButton ã³ã³ããŒãã³ã åçã¢ã€ã³ã³ã衚瀺ããããã¿ã³ãäœããŸãããã @expo/vector-icon ãã€ã³ã¹ããŒã«ããŸãã npx expo install @expo/vector-icons VS Code ã§ PhotoButton.js ãäœæããŸãã code components/PhotoButton.js äžèšã®ã³ãŒãã PhotoButton.js ã«æžã蟌ã¿ãŸãã import { StyleSheet, View, Pressable, Text } from "react-native"; import FontAwesome from "@expo/vector-icons/FontAwesome"; export default function PhotoButton({ label }) { return ( <View style={styles.buttonContainer}> <Pressable style={styles.button} onPress={() => alert("You pressed a button.")} > <FontAwesome name="picture-o" size={18} color="#25292e" style={styles.buttonIcon} /> <Text style={[styles.buttonLabel, {}]}>{label}</Text> </Pressable> </View> ); } const styles = StyleSheet.create({ buttonContainer: { width: 320, height: 68, marginHorizontal: 20, alignItems: "center", justifyContent: "center", padding: 3, borderWidth: 4, borderColor: "#ffd33d", borderRadius: 18, }, button: { borderRadius: 10, width: "100%", height: "100%", alignItems: "center", justifyContent: "center", flexDirection: "row", backgroundColor: "#fff", }, buttonIcon: { paddingRight: 8, }, buttonLabel: { color: "#25292e", fontSize: 16, }, }); äžèšã®ããã«è¡šç€ºãããŸããã ç»åã®éžæ ç»åãéžæããæ©èœãå®è£
ããŸãããã expo-image-picker ãã€ã³ã¹ããŒã«ããŸãã npx expo install expo-image-picker App.js ã§ pickImageAsync ãã¡ã³ã¯ã·ã§ã³ãå®è£
ããŸããããéžæããç»åã¯ã result.assets[0].uri ã«å
¥ã£ãŠããŸãã import * as ImagePicker from 'expo-image-picker'; const pickImageAsync = async () => { const result = await ImagePicker.launchImageLibraryAsync({ allowsEditing: true, quality: 1, }); if (!result.canceled) { alert(result.assets[0].uri); } else { alert('You did not select any image.'); } }; PhotoButton ã§ãã¿ã³ãæŒãããšãã®åäœãå®çŸ©ã§ããããã«ã onPress 屿§ã远å ããŸãããã export default function PhotoButton({ label, onPress }) { return ( <View style={styles.buttonContainer}> <Pressable style={styles.button} onPress={onPress} > <FontAwesome name="picture-o" size={18} color="#25292e" style={styles.buttonIcon} /> <Text style={styles.buttonLabel>{label}</Text> </Pressable> </View> ); } App.js ã§ PhotoButton ãæŒããããšãã«ã pickImageAsync ãã¡ã³ã¯ã·ã§ã³ãåŒã³åºããŸãã <PhotoButton label="Choose a photo" onPress={pickImageAsync} /> ImageViewer ã§éžæããç»åã衚瀺ã§ããããã«ã selectedImage 屿§ã远å ããŸãã export default function ImageViewer( { placeholderImageSource, selectedImage }) { const imageSource = selectedImage ? { uri: selectedImage } : placeholderImageSource; return <Image source={imageSource} style={styles.image} />; } App.js ã§ãåçãéžæããããã ImageViewer ã«è¡šç€ºããŸãã import { useState } from "react"; const PlaceholderImage = require("./assets/images/background-image.png"); export default function App() { const [selectedImage, setSelectedImage] = useState(null); const pickImageAsync = async () => { const result = await ImagePicker.launchImageLibraryAsync({ allowsEditing: true, quality: 1, }); if (!result.canceled) { setSelectedImage(result.assets[0].uri); } else { alert("You did not select any image."); } }; return ( <View style={styles.container}> <View style={styles.imageContainer}> <ImageViewer placeholderImageSource={PlaceholderImage} selectedImage={selectedImage} /> </View> <View style={styles.footerContainer}> <PhotoButton label="Choose a photo" onPress={pickImageAsync} /> <Button label="Use this photo" /> </View> <StatusBar style="auto" /> </View> ); } äžèšã®ããã«è¡šç€ºãããŸããã åããè¯ãã®ã§ãåç·šã¯ãããŸã§ãšããŸãã ãŸãšã Expoã®å
¬åŒãã¥ãŒããªã¢ã« ã¯ãé£æåºŠãã¡ããã©ããæãã§ãå®è·µçãªåã身ã«ã€ããªãšæããŸããããã ã JavaScript ãããªãTypeScriptã«ããŠã»ããã£ããšããã§ãã 仲éåé ç§ãã¡ã¯åãã°ã«ãŒãã§å
±ã«åããŠããã ãã仲éãåéããŠããŸãã çŸåšã以äžã®ãããªè·çš®ãåéããŠããŸãã ãœãªã¥ãŒã·ã§ã³ã¢ãŒããã¯ã AIãšã³ãžã㢠å·çïŒ @higa ïŒ Shodo ã§å·çãããŸãã ïŒ