카테고리 없음
[Vue.js] 날씨 웹앱 만들기
nh_3521099031483
2024. 4. 4. 14:17
기상청 API를 이용한 날씨 웹앱 만들기
단기예보 데이터를 이용해서 시간대별 날씨정보 구현하기
시간대별로 나누어 진게 아닌 카테고리별로 나누어져 있다.
모든 카테고리의 항목들이 필요하지는 않기 때문에 원하는 카테고리만 추출할 것이다
getters: { // arrayTemps가 원본데이터이다
filteredTempData(state) { // 기온
return state.arrayTemps.filter(temp => temp.category === 'TMP')
},
filteredPopData(state) { // 강수량
return state.arrayTemps.filter(temp => temp.category === 'POP')
},
filteredSkyData(state) { // 하늘상태
return state.arrayTemps.filter(temp => temp.category === 'SKY')
}
},
mapgetter 메서드를 이용해서 데이터를 vue파일의 computed메서드 안으로 불러와 준다.
...mapGetters('weatherApi', [
'filteredTempData',
'filteredPopData',
'filteredSkyData',
]),
현재 습도 풍속 강수확률을 나타내주기 위해서 해당 데이터들을 추출한다.
// state안에 선언
temporaryData: [
{
title: '습도',
value: '',
},
{
title: '풍속',
value: '',
},
{
title: '강수확률',
value: '',
},
],
// mutation안에 선언
SET_WEATHER_DATA(state, data) {
state.temporaryData[0].value = data.item[10].fcstValue + "%"; // 습도
state.temporaryData[1].value = data.item[4].fcstValue + "m/s"; // 풍속
state.temporaryData[2].value = data.item[7].fcstValue + "%"; // 강수확률
}
렌더링 될 vue 파일에 불러와 준다
computed: {
...mapState('weatherApi', [
'temporaryData',
]),
},
v-for 바인딩을 사용하여 렌더링
<div class="weatherData">
<div v-for="temporary in temporaryData" :key="temporary.title" class="detailData">
<p>{{ temporary.title }}</p>
<p>{{ temporary.value }}</p>
</div>
</div>
시간대별 날씨정보 바인딩
시간대에 맞는 강수량을 찾는 함수
methods: {
getPopValue(fcstTime) {
const popData = this.filteredPopData.find(data => data.fcstTime === fcstTime)
return popData ? popData.fcstValue : '-'
},
},
filteredTempData의 fcstTime(시간) 과 같은 시간의 강수량 데이터를 찾으면 되는 것이다.
<div class="timelyWeather" v-for="(temp, index) in filteredTempData" :key="index">
<div class="icon">
<img :src="images[index]" alt="hour" />
</div>
<div class="data">
<p class="time">
{{ temp.fcstTime.slice(0, 2) }}시
</p>
<p class="currentDegree">{{ temp.fcstValue }}°</p>
<div>
<img src="src/assets/images/drop.png" alt="빗방울" />
<p class="fall">{{ getPopValue(temp.fcstTime) }}%</p>
</div>
</div>
</div>
이미지 처리
이미지 경로를 동적으로 처리한다. 배포할 것이 아니기 때문에 로컬로 접근한다.
const images = state.arrayTemps.filter(temp => temp.category === 'SKY').reduce((acc, cur) => { // 함수를 사용하여 하늘 상태 데이터만 추출
// reduce 함수를 사용하여 추출된 데이터를 순회하며 이미지 경로 배열을 생성
const weatherIconValue = parseInt(cur.fcstValue); // 문자열을 정수형으로 변환
// console.log(typeof weatherIconValue)
const iconPath = (() => {
switch (weatherIconValue) {
case 1:
return 'src/assets/images/sunny.png';
case 2:
return 'src/assets/images/02d.png';
case 3:
return 'src/assets/images/03d.png';
case 4:
return 'src/assets/images/04d.png';
default:
return 'src/assets/images/sunny.png';
}
})();
acc.push(iconPath);
return acc;
}, []);
commit('SET_IMAGEPATH', images);
렌더링할 vue파일의 computed메서드 안에 store데이터를 사용하기 위해 선언해준다
images() {
return this.$store.state.weatherApi.images;
},
첫번째 이미지 데이터가 현재 하늘 상태의 이미지를 보여준다.
<div class="weatherIcon">
<img :src="images[0]" alt="MainLogo" />
</div>
filteredTempData의 갯수와 filteredSkyData의 갯수가 같이 때문에 images[index]로 v-for 바인딩 해준다
<div class="timelyWeather" v-for="(temp, index) in filteredTempData" :key="index">
<div class="icon">
<img :src="images[index]" alt="hour" />
</div>
....