스와이프메뉴 클릭하면 가운데오기

beomhak lee·2024년 5월 10일

work_tip

목록 보기
18/37

클릭시 해당엘리먼트가 가운데로 배치되는 스와이퍼를 만들어보자.

<div class="swiper-container snbSwiper" style="max-width:600px; margin: 0 auto;">
  <div class="swiper-wrapper">
    <div class="swiper-slide on"><a href="#"><span class="text">슬라이드1</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드2</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드3</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드4</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드5</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드6</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드7</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드8</span></a></div>
    <div class="swiper-slide"><a href="#"><span class="text">슬라이드9</span></a></div>
  </div>
</div>
   .snbSwiper {
  padding: 0 3px;
  box-sizing: border-box;
  background: #efefef;
}
.swiper-slide {
  width: auto !important;
}
.swiper-slide a {
  display: block;
  text-align: center;
}
.swiper-slide .text {
  margin: 0 5px;
  padding: 16px 5px 8px 5px;
  box-sizing: border-box;
  position: relative;
  display: inline-block;
  height: 47px;
  line-height: 43px;
  white-space: nowrap;
  font-size: 1rem;
  line-height: 1em;
  color: #333;
}
.on .text {
  color: #ffffff;
  font-weight: bold;
  border: 2px solid #000;
  border-radius: 20px;
  background: #000;
  padding: 0;
  line-height: 43px;
  padding: 0 1rem;
}
  const swiper = new Swiper('.snbSwiper', {
	slidesPerView: 'auto',
	preventClicks: true,
	preventClicksPropagation: false,
	observer: true,
	observeParents: true,
});

const $snbSwiperItem = document.querySelectorAll('.snbSwiper .swiper-wrapper .swiper-slide a');

$snbSwiperItem.forEach(function (item) {
	item.addEventListener('click', function () {
		let target = this.parentNode;

		$snbSwiperItem.forEach(function (item) {
			item.parentNode.classList.remove('on');
		});

		target.classList.add('on');
		muCenter(target);
	});
});

function muCenter(target) {
	const snbWrap = document.querySelector('.snbSwiper .swiper-wrapper');
	const targetRect = target.getBoundingClientRect(); // 클릭된 항목의 위치 및 크기 정보
	const box = document.querySelector('.snbSwiper'); // 보이는 화면의 전체 컨테이너 너비
	const boxHalf = box.clientWidth / 2; // 컨테이너의 절반 너비
	let pos; // 클릭된 항목을 중앙으로 이동하기 위한 위치 값
	let listWidth = 0; // 전체 슬라이더 항목의 너비 합계

	document.querySelectorAll('.snbSwiper .swiper-wrapper .swiper-slide').forEach(function (slide) {
		listWidth += slide.offsetWidth;
      // listWidth : slide의 찐 전체 너비를 구하기
	});

	const selectTargetPos = targetRect.left - snbWrap.getBoundingClientRect().left + target.offsetWidth / 2;
  
  // targetRect.left : 클릭한 요소의 왼쪽 끝이 어디에 있는지 
  // snbWrap.getBoundingClientRect().left : 슬라이드 왼쪽 끝이 어디에 있는지
  // target.offsetWidth / 2 : 클릭한 요소의 너비의 절반을 더해서 클릭한 요소의 중앙이 슬라이더 내에서 어디에 위치하는지 계산
  
  // selectTargetPos : 클릭된 요소가 슬라이더 내에서 어디에 위치하는지 계산
  

	if (selectTargetPos <= boxHalf) {
		// 왼쪽에 위치한 경우
		pos = 0;
	} else if (listWidth - selectTargetPos <= boxHalf) {
		// 오른쪽에 위치한 경우
		pos = listWidth - box.clientWidth;
	} else {
      	// 중앙에 위치한 경우
		pos = selectTargetPos - boxHalf;
	}

	// 애니메이션 적용
      snbWrap.style.transform = `translateX(${pos*-1}px)`;
      snbWrap.style.transitionDuration = '500ms';
}

참고 https://shubamba.tistory.com/52

0개의 댓글