Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- returnType
- CSS
- 성능최적화
- react
- 제네릭
- Chart.js
- javascript
- JS console
- 누구나 자료구조와 알고리즘
- 타입좁히기
- typescript
- 레이아웃쪼개기
- NonNullable
- 공통컴포넌트
- click and drag
- vue.js
- 티스토리꾸미기
- 리액트
- 반복줄이기
- React.js
- const 단언문
- 폰트적용하기
- 개발콘텐츠
- React Native
- utilty type
- 타입스크립트
- 커스텀
- 2022
- reactjs
- TSDoc
Archives
- Today
- Total
몽땅뚝딱 개발자
[Swiper] 세로형 슬라이드 배너 제작하기 / vertical 본문
Swiper로 개발할 때 가로형에 슬라이드가 1개인 것만 구현해봤었는데 이번 개발건에 세로형+여러 슬라이드 구성이 필요했다.
이번에는 예전과 달리 "공통"이라는 키워드에 맞춰 개발하려고 노력했고 그것을 기록하는 글..✏️
vue-awesome-swiper를 사용했다.
$ npm i vue-awesome-swiper
📄 공통컴포넌트
- prop으로 넘어온 isVertical(=세로여부) 값에 따라 style이 나뉘어진다.
- 공통적으로 사용하려면 콘텐츠 영역은 분리돼야 할 것 같아 <swiper-slide> 영역은 <slot>으로 따로 받아서 구현했고, 콘텐츠 영역의 width, height를 받아서 슬라이드 배너의 너비와 높이를 계산했다.
<template>
<div
class="floating-banner"
:style="{ width: `${isVertical ? contentWidth : computedLength}px` }"
>
<div class="floating-banner__contents">
<swiper
ref="floatingBannerSwiper"
:style="isVertical ? { height: `${computedLength}px` } : { width: `${computedLength}px` }"
:options="swiperOption"
>
<!-- 콘텐츠 영역은 이렇게 슬롯으로 받았다. -->
<slot></slot>
</swiper>
<button
class="floating-button__up w-swiper-button-prev"
:class="!isVertical && 'is-horizontal'"
>
<IconArrowUp />
</button>
<button
class="floating-button__down w-swiper-button-next"
:class="!isVertical && 'is-horizontal'"
>
<IconArrowDown />
</button>
</div>
</div>
</template>
다음은 script 부분이다.
- isVertical을 prop으로 받아 세로형, 가로형으로 바로 변경할 수 있도록 처리했다. Swiper의 세로형은 높이를 따로 지정해주어야하는데 computed의 computedLength가 그 역할을 수행한다.
- Swiper 옵션 중 direction에 'vertical'을 준다.
<script>
import { Swiper } from 'vue-awesome-swiper'
export default {
name: 'FloatingSideBanner',
components: { Swiper },
props: {
list: {
type: Array,
required: true,
},
// 노출할 콘텐츠의 개수
count: {
type: Number,
default: 3,
},
// 각 콘텐츠의 너비 (단위: px)
contentWidth: {
type: Number,
required: true,
},
// 각 콘텐츠의 높이 (단위: px)
contentHeight: {
type: Number,
required: true,
},
// 콘텐츠 사이의 간격 (단위: px)
gap: {
type: Number,
default: 10,
},
// 슬라이드 속도
speed: {
type: Number,
default: 5,
},
useAutoplay: {
type: Boolean,
default: true,
},
useLoop: {
type: Boolean,
default: true,
},
isVertical: {
type: Boolean,
default: true,
},
},
data() {
return {
delay: this.speed,
swiperOption: {
direction: this.isVertical ? 'vertical' : 'horizontal', // 가로형, 세로형
effect: 'slide',
slidesPerView: this.count,
spaceBetween: this.gap,
loop: this.useLoop,
simulateTouch: false, // 사용자가 터치하여 슬라이드를 넘기는 설정
navigation: { // 버튼 클래스를 연결해줘야 한다.
nextEl: '.w-swiper-button-next',
prevEl: '.w-swiper-button-prev',
},
},
}
},
computed: {
swiper() {
return this.$refs.floatingBannerSwiper.$swiper
},
// 여기서 높이를 설정한다.
computedLength() {
return this.contentHeight * this.count + this.gap * (this.count - 1)
},
},
created() {
this.init()
},
methods: {
init() {
if (this.useAutoplay) {
this.swiperOption = {
autoplay: {
delay: this.delay * 1000,
disableOnInteraction: false,
},
...this.swiperOption,
}
}
},
},
}
</script>
다음은 style 영역이다.
가로형, 세로형 여부에 따라 prev, next 버튼을 transform의 rotate 속성으로 뒤집어주었고 위치를 변경해주었다.
<style lang="scss" scoped>
.floating {
&-banner {
z-index: 10;
position: absolute;
top: 50%;
transform: translateY(-50%);
.swiper-container {
width: 100%;
margin: 0 auto;
}
&__contents {
display: flex;
justify-content: center;
}
}
&-button {
:is(&__up, &__down) {
position: absolute;
cursor: pointer;
z-index: 5;
border: none;
background-color: transparent;
&.is-horizontal {
top: 50%;
transform: translateY(-50%);
}
}
&__up {
top: -12px;
transform: translateY(-100%);
&.is-horizontal {
left: 0px;
transform: translate(-100%, -50%) rotate(-90deg);
}
}
&__down {
bottom: -12px;
transform: translateY(100%);
&.is-horizontal {
right: 0;
transform: translate(100%, -50%) rotate(-90deg);
}
}
}
}
</style>
📄 컴포넌트 호출부
<floating-side-banner
:list="floatingBannerList"
:content-width="160"
:content-height="160"
:gap="12"
>
<swiper-slide v-for="item in floatingBannerList">
<div class="banner-content">
{{ item.content }}
</div>
</swiper-slide>
</floating-side-banner>
floatingBannerList: [
{ content: 0 },
{ content: 1 },
{ content: 2 },
{ content: 3 },
{ content: 4 },
{ content: 5 },
{ content: 6 },
]
"간단한 prop 변수를 몇 개 수정하는 것 만으로 가로형, 세로형을 자유로이 변경 할 수 있을까?"로 시작된 고민의 늪.
prop으로 온갖 값을 받았다가 다시 지웠다가 하며 지금 내가 생각할 수 있는, 이 컴포넌트를 구성하기 위한 최소한의 값으로 구성한 것 같다.
(미래의 내 자신아.. 평가해줘..!!!!)
개발 할 때는 머리싸매며 고민했는데 적고보니까 별게 없다...🤔
다음부터는 codepen 링크까지 넣어봐야겠다.
'Development > Javascript' 카테고리의 다른 글
reverse() vs. reversed() (0) | 2024.01.14 |
---|---|
[Javascript] 듀얼 모니터에서 팝업 중앙에 띄우기 (0) | 2024.01.09 |
[Javscript] lodash (작성 중) (0) | 2023.07.23 |
[Javascript] 자바스크립트에서 Iterator 구현하기 (0) | 2023.05.20 |
[JavaScript] 문자열의 바이트(byte) 구하기 (1) | 2023.03.24 |
Comments