반응형
1. 기존 코드
나는 니꼬쌤의 react native 기본 강의를 보면서 간단한 날씨 어플을 만들었다.
// import { StatusBar } from 'expo-status-bar';
import * as Location from "expo-location";
import { useEffect, useState } from 'react';
import { StyleSheet, Text, View, ScrollView, Dimensions, ActivityIndicator } from 'react-native';
const {width:SCREEN_WIDTH} = Dimensions.get("window");
const API_KEY ="15195b65e8894febd84d5a8e8357ef06";
export default function App() {
const [city, setCity] = useState("Loading...");
const [days, setDays] = useState([]);
const [ok, setOk] = useState(true);
const getWeather = async () =>{
const {granted} = await Location.requestForegroundPermissionsAsync();
// console.log(permission);
if(!granted){
setOk(false);
}
const {coords:{latitude, longitude}} = await Location.getCurrentPositionAsync({accuracy:5});
const location = await Location.reverseGeocodeAsync({latitude, longitude}, {useGoogleMaps:false});
setCity(location[0].city);
const response = await fetch(`https://api.openweathermap.org/data/2.5/forecast?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`);
const json = await response.json();
setDays(json.list);
// console.log(json.list[0]);
}
useEffect(()=>{
getWeather();
},[]);
return (
<View style={styles.container}>
<View style={styles.city}>
<Text style={styles.cityName}>{city}</Text>
</View>
<ScrollView
pagingEnabled
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.weather}>
{
days.length === 0?(
<View style={styles.day}>
<ActivityIndicator Indicator style={{marginTop:10}} color="white" size="large"/>
</View>
):(
days.map((day, index)=>{
return(
<View key={index} style={styles.day}>
<Text style={styles.temp}>{parseFloat(day.main.temp).toFixed(1)}</Text>
<Text style={styles.description}>{day.weather[0].main}</Text>
<Text style={styles.TinyText}>{day.weather[0].description}</Text>
</View>
);
})
)
}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container:{
flex:1,
backgroundColor:"tomato"
},
city:{
flex:1,
justifyContent:"center",
alignItems:"center",
},
cityName:{
fontSize:58,
fontWeight:"500",
color:"white",
paddingTop:100,
},
weather:{
marginTop:50,
},
day:{
width:SCREEN_WIDTH,
alignItems:"left",
paddingLeft:30,
},
temp:{
marginTop:50,
fontSize:118,
fontWeight:"600",
color:"white",
},
description:{
marginTop:-20,
fontSize:40,
color:"white",
},
TinyText:{
fontSize:20,
color:"white",
}
});
결과
이제 여기에 날씨 아이콘을 넣어줄 것이다.
2. 날씨의 모든 경우
위 링크에서 아이콘 리스트를 볼 수 있다.
일단 우리가 받을 수 있는 모든 날씨의 경우를 생각해보자!
https://openweathermap.org/weather-conditions
여기서 날씨의 모든 경우를 확인할 수 있다.
const icons = {
"Clouds" : "cloudy",
"Clear" : "day-sunny",
"Atmosphere":"cloudy-gusts",
"Snow":"snow",
"Rain":"rains",
"Drizzle":"rain",
"Thunderstorm":"lightning",
}
이것이 모든 경우이다.
3. 아이콘 적용
1. expo icons를 import 해준다.
import {Fontisto} from "@expo/vector-icons";
2. 사용한다.
days.map((day, index)=>{
return(
<View key={index} style={styles.day}>
<View style={{flexDirection:"row", alignItems:"center", width:"100%",justifyContent:"space-between"}}>
<Text style={styles.temp}>{parseFloat(day.main.temp).toFixed(1)}</Text>
<Fontisto name="cloudy" size={68} color="white"/>
</View>
<Text style={styles.description}>{day.weather[0].main}</Text>
<Text style={styles.TinyText}>{day.weather[0].description}</Text>
</View>
);
})
이럴 경우엔 슬라이더의 내용이 다같은 cloudy를 쓰는 것이기 때문에 동적으로 변경해줘야 한다.
<Fontisto name={icons[day.weather[0].main]} size={68} color="white"/>
이런식으로 key값으로 접근하게 도와준다.
day.weather[0].main에는 Cloudy, Rain과 같은 날씨 정보가 들어있고, 그 value 값으로 아이콘 이름이 적혀있다.
const icons = {
"Clouds" : "cloudy",
"Clear" : "day-sunny",
"Atmosphere":"cloudy-gusts",
"Snow":"snow",
"Rain":"rains",
"Drizzle":"rain",
"Thunderstorm":"lightning",
}
이런식으로 말이다.
이걸 써서 동적으로 날씨 아이콘을 날씨에 맞게 쓸 수 있다.
4. 전체 코드
// import { StatusBar } from 'expo-status-bar';
import * as Location from "expo-location";
import { useEffect, useState } from 'react';
import { StyleSheet, Text, View, ScrollView, Dimensions, ActivityIndicator } from 'react-native';
import {Fontisto} from "@expo/vector-icons";
const {width:SCREEN_WIDTH} = Dimensions.get("window");
const API_KEY ="15195b65e8894febd84d5a8e8357ef06";
const icons = {
"Clouds" : "cloudy",
"Clear" : "day-sunny",
"Atmosphere":"cloudy-gusts",
"Snow":"snow",
"Rain":"rains",
"Drizzle":"rain",
"Thunderstorm":"lightning",
}
export default function App() {
const [city, setCity] = useState("Loading...");
const [days, setDays] = useState([]);
const [ok, setOk] = useState(true);
const getWeather = async () =>{
const {granted} = await Location.requestForegroundPermissionsAsync();
// console.log(permission);
if(!granted){
setOk(false);
}
const {coords:{latitude, longitude}} = await Location.getCurrentPositionAsync({accuracy:5});
const location = await Location.reverseGeocodeAsync({latitude, longitude}, {useGoogleMaps:false});
setCity(location[0].city);
const response = await fetch(`https://api.openweathermap.org/data/2.5/forecast?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`);
const json = await response.json();
setDays(json.list);
}
useEffect(()=>{
getWeather();
},[]);
return (
<View style={styles.container}>
<View style={styles.city}>
<Text style={styles.cityName}>{city}</Text>
</View>
<ScrollView
pagingEnabled
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.weather}>
{
days.length === 0?(
<View style={{...styles.day, alignItems:"center"}}>
<ActivityIndicator Indicator style={{marginTop:10}} color="white" size="large"/>
</View>
):(
days.map((day, index)=>{
return(
<View key={index} style={styles.day}>
<View style={{flexDirection:"row", alignItems:"center", width:"100%",justifyContent:"space-between"}}>
<Text style={styles.temp}>{parseFloat(day.main.temp).toFixed(1)}</Text>
<Fontisto name={icons[day.weather[0].main]} size={68} color="white"/>
</View>
<Text style={styles.description}>{day.weather[0].main}</Text>
<Text style={styles.TinyText}>{day.weather[0].description}</Text>
</View>
);
})
)
}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container:{
flex:1,
backgroundColor:"tomato"
},
city:{
flex:1,
justifyContent:"center",
alignItems:"center",
},
cityName:{
fontSize:58,
fontWeight:"500",
color:"white",
paddingTop:100,
},
weather:{
marginTop:50,
},
day:{
width:SCREEN_WIDTH,
alignItems:"left",
paddingLeft:30,
},
temp:{
marginTop:50,
fontSize:88,
fontWeight:"600",
color:"white",
},
description:{
marginTop:-20,
fontSize:40,
color:"white",
},
TinyText:{
fontSize:20,
color:"white",
}
});
반응형
'FE > react-native' 카테고리의 다른 글
DropDownPicker 속성 파헤치기 (0) | 2023.10.02 |
---|---|
react-native 로딩바 적용해보기 (0) | 2023.09.03 |
react-native에서 open weather api를 이용해 날씨 정보 가져오기 (0) | 2023.09.02 |
react-native에서 expo-location을 이용해 유저 위치 정보 가져오기 (0) | 2023.09.02 |
react native는 기본 flex box 기반이다. (0) | 2023.09.02 |