일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 1일1코테
- 코테준비
- 프로그래밍
- 코테공부
- 프로그래머스
- 정보처리기사
- mysql
- 알고리즘스터디
- next.js 에러
- 자바스크립트
- 알고리즘공부
- 코테스터디
- 개발자
- CSS
- 프로그래머스알고리즘
- html
- 프로그래머스 코테
- 프로그래머스코테
- 프로그래머스 코딩테스트
- 코딩
- 알고리즘문제
- 정처기기출
- 프로그래머스코딩테스트
- 프로그래머스 Lv.0
- 프로그래머스 레벨0
- next.js
- js
- 프로그래머스 알고리즘
- 코딩테스트
- Redux-Toolkit
- Today
- Total
계발하는 개발자
[Vue + JS] 무한 롤링 배너 기능 구현하는 방법 본문
일전에 학원에서 진행했던 초창기 프로젝트에서 marquee(움직이는 텍스트) 구현하듯이 좌측으로 롤링되는 무한 롤링배너를 또 구현해야 했다.
위에서 이미지 배너 뒤에 움직이는 텍스트가 marquee다.
기억 상으로 html+css 만으로 움직이게 했던 것 같다.
(이미지 배너는 다른 방법으로 구현했으며, 원래는 멈춰있다가 커서가 해당 슬라이드 영역을 한 번 건드리고 가면 그때부터 움직이고, 움직이는 슬라이드 위에 커서를 놓으면 움직임을 멈추도록 했다.)
이번엔 다른 색다른 방법으로 구현하고 싶어서 찾아봤더니 Javascript cloneNode 함수를 이용해서 구현하는 방법이 있었다.
그 원리는 즉슨, li를 감싸는 wrap이라는 요소가 있으면 wrap 요소를 clone해서 또 다른 wrap2 요소를 만들고,
display: flex 로 한 행에 배치시킨 다음에 css 애니메이션을 wrap 요소마다 적용하는 것이다.
무한 롤링 배너 만들기
무한 롤링 배너는 원본배너와 복제배너를 한 방향으로 이동시켜주면서 배너 2개가 번갈아가며 뷰포트에 나타나는 형식으로 실제 화면상에서 보이는 동작은 하나의 배너가 무한 롤링하는 것처럼 보이게 된다.
작동 원리
1. 애니메이션 초기 상태
배너1 복사한 후 클론한 배너를 .md_wrap(배너 부모박스) 뒤쪽에 삽입해준다.
그런 후에 부모박스에 display: flex 적용하여 한 줄에 배치시킨다. 배너1 끝부분이 약간 잘린 채로 뷰포트 화면에는 아직 배너1만 보이게 된다.(이때 배너1, 배너2 구분을 위해 각각의 배너에 고유id값을 부여한다.)
2. 배너 너비만큼 배너1, 2 왼쪽 이동
css 키프레임을 이용해 왼쪽 방향으로 이동하는 애니메이션을 적용시킨다.
배너1,2가 translateX(-100%)만큼 왼쪽 이동하면서 배너1은 뷰포트 바깥으로 밀려나게 되고,배너2는 앞서 배너1 초기 위치만큼 이동한다. 그래서 현재 화면에서는 배너2가 보이게 된다.
'0%'일 때: 배너의 원래 위치이며, 애니메이션의 시작 지점이다 (transform: translateX(0)).
'50%일 때': 배너1은 왼쪽으로 슬라이드하여 이동한다 (transform: translateX(-100%)).
3. 배너1이 배너2 뒤쪽으로 이동
배너1이 다시 오른쪽으로 이동해서 들어오게 된다 transform: translateX(100%).
배너2는 다시 -100%만큼 왼쪽으로 이동해서 (총 -200%) 뷰포트 화면 밖으로 나가게 된다.
그리고 이 과정이 반복되면서 무한 롤링 배너가 구현되는 것이다.
'50.01%일 때': 배너1 다시 오른쪽 방향으로 이동해서 배너2 뒤에 위치한다 (transform: translateX(100%).
'100%일 때': 배너2는 다시 -100%만큼 왼쪽 이동해서 (총 -200% 이동) 뷰포트 밖으로 나간다.
.md_wrap {
overflow: hidden;
display: flex;
gap: -4px;
ul {
display: flex;
li {
width: 340px;
height: 544px;
margin: 0 8px;
background-color: #fff;
display: flex;
}
}
// 롤링배너 애니메이션
#roller1 {
animation: rollingleft1 90s linear infinite;
}
#roller2 {
animation: rollingleft2 90s linear infinite;
}
}
@keyframes rollingleft1 {
0% { transform: translateX(0)}
50% { transform: translateX(-100%)}
50.01% { transform: translateX(100%)}
100% { transform: translateX(0)}
}
@keyframes rollingleft2 {
0% {transform: translateX(0)}
100% {transform: translateX(-200%)}
}
<!-- 4. 미디어섹션(컴포넌트)-->
<section class="main_media">
<h3>Media</h3>
<div class="md_wrap">
<div class="md_list">
<ul>
<MedComp v-for="(v, i) in mData" :key="i" :matchmedia="v" :dpt1val="v.depth1" :dpt2val="v.depth2"/>
</ul>
</div>
</div>
</section>
methods: {
rollBan() {
// 롤링 배너 복제본 생성
let roller = document.querySelector('.md_list');
roller.id = 'roller1'; // 아이디 부여
// 노드 복제 (기본값은 false, 자식 노드까지 원하면 true)
let clone = roller.cloneNode(true);
clone.id = 'roller2';
document.querySelector('.md_wrap').appendChild(clone); // .md_wrap 하위 자식으로 넣기
document.querySelector('#roller1').style.left = '0px';
document.querySelector('#roller2').style.left = document.querySelector('.md_list > ul').offsetWidth + 'px';
},
}
<!-- 아래는 MedComp Template -->
<template>
<li>
<a href="#">
<!-- 썸네일 출력 영역 -->
<div class="media_thumb">
<img v-bind:src="tumbimg" alt="대표썸네일" />
<span class="mlogo">
<img src="/images/logo/logo_y.jpg" alt="sns계정명" />
shoopen_official
</span>
</div>
<div class="media_depth">
<!-- 상품1 출력 영역 -->
<div class="prod1bx">
<div class="left_img">
<img v-bind:src="dpt1img" alt="상품이미지1" />
</div>
<div class="right_txt">
<p>{{ dpt1name }}</p>
<em>{{ setComma(dpt1price) }}</em>
</div>
</div>
<!-- 상품2 출력 영역 -->
<div class="prod2bx">
<div class="left_img">
<img v-bind:src="dpt2img" alt="상품이미지2" />
</div>
<div class="right_txt">
<p>{{ dpt2name }}</p>
<em>{{ setComma(dpt2price) }}</em>
</div>
</div>
</div>
</a>
</li>
</template>
결과 화면
배너1,2가 순환 반복되면서 이동된다 :)
* 기능구현 참고자료
느낀점
구글링을 하며 찾은 다른 구현 방법을 이게 왜 원리가 이렇게 되는지를 내가 다시 따져보고 적용해보는 과정이 참 재밌었다!
그리고 이 과정에서 다른 사람은 어떤 방식으로 접근했는가를 살펴볼 수 있었어서 '아 이런 방식으로도 할 수 있구나' 하고 뇌가 말랑해진 느낌을 받았다.
'📌 Language > Javascript' 카테고리의 다른 글
[Vue + JS] 쇼핑몰 상품 정렬 버튼 구현 (feat. select 태그 안쓰고 직접 비슷하게 만들기) (0) | 2023.09.29 |
---|---|
[Vue + JS] 상품 정렬 기능 구현 - sort 메서드 (0) | 2023.09.29 |
[Javascript/ javascript localstorage 저장] JSON.stringify(), JSON.parse() (0) | 2023.09.15 |
[JS] 렉시컬 스코프와 클로저 (0) | 2023.08.21 |
[JS] 배열을 비교, 정렬하는 방법 | sort 메서드 (0) | 2023.06.21 |
dev_genie
@dev_genie
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!