📢 들어가며
그동안 게을러져서 포스팅이 살짝 늦었다... 다시 화이팅해보자!
이번 포스팅은 지난 포스팅에서 이어진다.
지난 포스팅에선 화면에 지도를 띄우고 대략적인 UI 틀을 잡았었다.
이번 포스팅에선 구체적인 UI 를 구현해볼 것이다.
모든 소스코드는 깃헙에서 확인할 수 있다.
🍜 UI 설계
이번에도 대충 그려 설계를 해보았다.
지도에서 특정 위치를 선택하고 나면 좌측 사이드바가 활성화되고 위 이미지와 같은 정보를 입력할 수 있게 된다.
사이드 바에선 음식점의 이름, 이미지, 위치정보, 별점, 평가를 보여준다.
🍜 Bootstrap 설치
본격적인 UI 구현을 위해서 Bootstrap을 사용할 것이다.
Bootstrap 을 설치해보자.
vue add bootstrap-vue
Vue CLI3로 설치를 했기 때문에 Vue CLI 플러그인을 활용해 Bootstrap을 설치해주는 것이다.
별다른 설정없이 bootstrap을 주입할 수 있다.
🍜 사이드바 UI 구현
이제 버튼으로 사이드바를 펼쳤다 접었다하고,
접혀진 상태에서 지도를 클릭했을 때 사이드바가 활성화 되도록 구현해 볼 것이다.
Bootstrap 을 설치하고 나면 <BButton>
같은 Bootstrap에서 제공하는 Components들을 쓸 수 있다.
사이드 바 옆에 사이드바를 활성화할 수 있는 버튼을 만들어 보자.
<template>
<div class="side-bar-wrapper">
<VueResizable
class="resizable-side-bar"
:width="500"
:min-width="500"
:max-width="Infinity"
:active="['r']"
v-if="isVisibleSideBar"
>
<div class="side-bar">
</div>
</VueResizable>
<BButton
class="side-bar-active-btn"
size="sm"
@click="showSideBar"
>
{{ isVisibleSideBar ? '닫힘' : '열림' }}
</BButton>
</div>
</template>
<script>
import VueResizable from 'vue-resizable';
export default {
name: 'SideBar',
components: {
VueResizable
},
data() {
return {
isVisibleSideBar: true
}
},
methods: {
showSideBar() {
this.isVisibleSideBar = !this.isVisibleSideBar;
}
}
}
</script>
<style lang="scss" scoped>
.side-bar-wrapper {
display: flex;
> .resizable-side-bar {
> .side-bar {
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
> .side-bar-active-btn {
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: #000000;
padding: 0;
border: none;
border-radius: unset;
color: #fff;
opacity: 0.5;
width: 40px;
height: 40px;
}
}
</style>
frontend/src/components/SideBar.vue
버튼 위치를 잡기 위해 flex 를 쓰고, Side Bar와 똑같이 opacity를 줘서 구현했다.showSideBar()
메소드로 사이드바가 열고 닫힐 수 있도록 하였고, 열고 닫을 때 버튼의 글씨가 바뀌게 했다.
이제 사이드바 내 UI 를 구현해보자
<template>
<div class="side-bar-wrapper">
<VueResizable
class="resizable-side-bar"
:width="500"
:min-width="500"
:max-width="Infinity"
:active="['r']"
v-if="isVisibleSideBar"
>
<div class="side-bar">
<div class="title-area">
<BInput placeholder="맛집 이름을 입력해주세요."/>
</div>
<div class="image-area">
<div class="iw-file-input">
사진을 업로드 해주세요
</div>
</div>
<div class="location-info-area">
<BInput placeholder="위치 정보 직접 입력하기"/>
</div>
<div class="rate-area">
<BFormRating />
</div>
<div class="review-area">
<BFormTextarea
ref="textarea"
placeholder="후기를 입력해주세요."
/>
</div>
</div>
</VueResizable>
<BButton
class="side-bar-active-btn"
size="sm"
@click="showSideBar"
>
{{ isVisibleSideBar ? '닫힘' : '열림' }}
</BButton>
</div>
</template>
<script>
import VueResizable from 'vue-resizable';
export default {
name: 'SideBar',
components: {
VueResizable
},
data() {
return {
isVisibleSideBar: true
}
},
methods: {
showSideBar() {
this.isVisibleSideBar = !this.isVisibleSideBar;
}
}
}
</script>
<style lang="scss" scoped>
.side-bar-wrapper {
display: flex;
color: #fff;
> .resizable-side-bar {
> .side-bar {
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 10px;
> .title-area {
padding: 20px 10px;
input, input::placeholder, input:focus {
font-size: 2rem;
font-weight: bold;
color: #fff;
box-shadow: none;
background: none;
border: none;
}
}
> .image-area {
padding: 0 10px;
> .iw-file-input {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.3rem;
border: 5px dashed rgb(255, 255, 255, 0.5);
border-radius: 10px;
height: 250px;
background-color: rgb(255, 255, 255, 0.5);
}
}
> .location-info-area {
padding: 10px;
input, input::placeholder, input:focus {
font-size: 1rem;
color: #fff;
box-shadow: none;
background: none;
border: none;
}
}
> .rate-area {
padding: 0 20px;
text-align: center;
output {
font-size: 2rem;
color: #ffdd00;
background: none;
border: none;
box-shadow: none;
}
}
> .review-area {
padding: 20px 10px;
textarea, textarea::placeholder {
min-height: 300px;
resize: none;
color: #fff;
background: none;
border: none;
box-shadow: none;
}
/* width */
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #555;
}
}
}
}
> .side-bar-active-btn {
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: #000000;
padding: 0;
border: none;
border-radius: unset;
color: #fff;
opacity: 0.5;
width: 40px;
height: 40px;
}
}
</style>
frontend/src/components/SideBar.vue
설계했던 이미지 대로 UI를 구현해보았다. 대부분 Bootstrap을 활용했다.input
은 네모 박스가 아니라 글씨만 보이도록 구현했고,
파일 업로드 부분은 아직 잘 모르겠어서 일단 UI 틀만 잡아놨다.
UI 구현 부분은 딱히 설명할 것이 없어보이지만,
신경 쓴 부분에 대해서만 살짝 언급해보자면...
개인적으로 위 그림과 같은 스크롤바 디자인이 굉장히 보기 싫었다.
브라우저마다 스크롤바가 다르게 보이는 것도 맘에 들지 않아,
W3School 를 참고하여 스크롤바 디자인을 바꿔 주었다.
/* width */
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background: #f1f1f1;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #888;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #555;
}
frontend/src/components/SideBar.vue
🍜 사이드바 UI 디테일 살리기
뭔가 지금 UI는 허전해보여서, 아이콘을 추가하고 글꼴을 바꿔주기로 했다.
🍬 Font Awesome 아이콘 추가
Bootstrap에서 Icon을 제공해주긴 하지만, 나는 Font Awesome Icon 이 좀 더 익숙해서 이를 사용하기로 했다.
설치
$ npm i @fortawesome/vue-fontawesome
$ npm i @fortawesome/fontawesome-svg-core
$ npm i @fortawesome/free-solid-svg-icons
@fortawesome/fontawesome-svg-core
- Fontawesome의 SVG파일을 던져주는 역할을 한다.
- 반드시 필요!
@fortawesome/vue-fontawesome
- 던져준 SVG파일을 Vue에서 사용할 수 있게 해주게 한다.
- 반드시 필요!
@fortawesome/free-solid-svg-icons
- 아이콘 모음이라고 생각하면 된다.
- 종류(무료)에는 solid, regular, brands 가 있다.
- solid 는 색이 채워진? 두꺼운? 느낌의 아이콘 모음이다.
설치 후 package.json
의 dependecies
를 보면 잘 설치된 것을 확인할 수 있다.
설치된 FontAwesome Icon을 관리하는 파일을 만들어줄 것이다.
src
디렉토리 아래에 common
폴더를 파고 Icons.js
파일을 생성하자.
import Vue from 'vue';
// 0. 편의를 위해 아이콘은 알파벳 순서대로 추가하자.
// 1. 설치했던 fontawesome-svg-core 와 vue-fontawesome
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
// 2. 설치했던 아이콘 파일에서 원하는 아이콘 불러오기
import {
faAngleLeft,
faAngleRight,
faLocationDot,
} from "@fortawesome/free-solid-svg-icons";
// 3. 불러온 아이콘을 라이브러리에 담기
library.add(faAngleLeft);
library.add(faAngleRight);
library.add(faLocationDot);
// 4. fontawesome 아이콘을 Vue 템플릿에서 사용할 수 있도록 등록
Vue.component("FontAwesomeIcon", FontAwesomeIcon);
frontend/src/common/Icons.js
생성한 Icons.js
를 전역에서 사용할 수 있도록 main.js
에 아래 코드를 추가하면 끝.
import '@/common/Icons.js';
frontend/src/main.js
이제 아이콘 사용할 일이 있으면 /src/common/Icons.js
에서 원하는 아이콘을 import
해오고, library
에 add
시켜주기만 하면된다.Vue.component("FontAwesomeIcon", FontAwesomeIcon);
를 통해 Vue component로 등록해줬기 때문에 <FontawesomeIcon icon="location-dot" />
과 같이 구현할 수 있다.
이제 아이콘을 적용해보자.
열림, 닫힘 버튼을 화살표 아이콘으로 변경하고,
위치 정보 입력란 앞쪽에 아이콘을 추가해줄 것이다.
// ...
<div class="location-info-area">
<FontAwesomeIcon icon="location-dot" />
<BInput placeholder="위치 정보 직접 입력하기"/>
</div>
// ...
<BButton
class="side-bar-active-btn"
size="sm"
@click="showSideBar"
>
<FontAwesomeIcon :icon="isVisibleSideBar ? 'angle-left' : 'angle-right'" />
</BButton>
// ...
// css
> .location-info-area {
padding: 10px 20px;
display: flex;
align-items: center;
// ...
}
frontend/src/components/SideBar.vue
확실히 아이콘을 추가하는 편이 더 예뻐보인다!
🍬 Font 적용
Font를 적용하기 위한 방법에는 3가지가 있다
1. 로컬PC에 설치하기
2. font 파일들을 보관하여 불러오기
3. Web CDN
인터넷이 안되는 환경에서도 동작하기 위해, 그리고 로컬PC에 설치할 수 없는 경우를 대비하여 font 파일들을 따로 보관하여 불러오는 방식으로 진행했다.
src/assets 폴더 하위에 fonts 폴더를 파고 원하는 폰트를 다운로드하여 추가한다.
나는 '나눔스퀘어'와 '나눔바른고딕'을 추가했다.
frontend/src/assets/scss/vendors/bootstrap-vue
를 보면 _custom.scss
라는 파일이 보일 것이다.
이는 부트스트랩으로부터 추가된 커스텀 css 파일로, bootstrap 이 외의 css를 전역적으로 추가해주고 싶을 때 사용할 수 있다.
아래 코드를 추가하여 추가한 폰트를 사용할 수 있게 하자
//======================= CUSTOM ==================================
// 글꼴
@font-face {
font-family: 'Nanum Square';
src: url('~@/assets/fonts/NanumSquare_acEB.ttf') format('truetype');
}
@font-face {
font-family: 'Nanum Barun Gothic';
src: url('~@/assets/fonts/NanumBarunGothic.ttf') format('truetype');
}
frontend/src/assets/scss/vendors/bootstrap-vue/_custom.scss
'나눔스퀘어'는 제목부분의 폰트를 변경해주는 데에 사용할 것이고,
'나눔바른고딕'은 전역적으로 선언해줄 것이다.
// ...
> .title-area {
// ...
input, input::placeholder, input:focus {
font-family: 'Nanum Square', serif;
// ...
}
}
frontend/src/components/SideBar.vue
// ...
<style lang="scss">
@import "~@/assets/scss/vendors/bootstrap-vue/index";
#app {
// ...
frontend/src/App.vue
글꼴이 제대로 적용된 것을 확인할 수 있었다!🎉
이번 포스팅에선 사이드 바의 UI를 구현해보았다.
다음 포스팅에선 이번 포스팅을 통해 알게된 _custom.scss
파일로 재사용가능한 기능을 구현해보고,
지도를 클릭하여 위치 정보를 입력할 수 있는 기능을 구현해보도록하겠다.
댓글, 하트, 피드백은 언제나 환영입니다!😇
'개인 프로젝트' 카테고리의 다른 글
맛집 지도 만들기(6) - 리뷰 지도에 표시하기 및 리뷰 수정, 삭제 (2) | 2022.07.22 |
---|---|
맛집 지도 만들기(5) - CRUD API 구현하기 (feat. Axios, 함수형 컴포넌트) (1) | 2022.06.19 |
맛집 지도 만들기(4) - 지도 클릭 이벤트로 주소 입력 받기 (Nominatim API) (12) | 2022.05.16 |
맛집 지도 만들기(2) - OpenLayers 지도 띄우기 (4) | 2021.12.05 |
맛집 지도 만들기(1) - Spring Boot + Vue.js 설치 및 연동하기 (7) | 2021.11.27 |