마우스 이벤트 (mouse event)
mousedown : 마우스로 누를 때 발동
mouseup : 마우스를 뗄 때
mousemove : (해당 요소에서) 마우스를 움직일 때
- e.clientX : 현재 마우스 위치의 X좌표
document.getElementsByClassName('slide-box')[0].addEventListener('mousemove', function(e) {
console.log(e.clientX)
});
터치 이벤트 (touch event)
touchstart : 터치 시작 시 발동
touchend : 터치 종료 시 발동
- e.changedTouches[0].clientX : 현재 터치 위치의 X좌표
touchmove : 터치 중 발동
- e.touches[0].clientX : 현재 터치 위치의 X좌표
이미지(img) 드래그 가능
draggable : true는 가능, false는 불가능
<img src="xiang1.png" draggable="false">
Hammer.js
- 마우스 & 터치 라이브러리
- 브라우저 간 호환성을 잡아줌
- 이벤트 리스너가 1개만 필요함
- 스와이프, pinch, rotate 이벤트도 제공함
캐러셀 스와이프(Carousel Swipe)
구현 계획
변수
- 마우스 눌렀을 때의 좌표 변수(시작 좌표)
- 마우스를 눌렀나 확인할 변수 - 마우스 사용 안할 때는 비활성화
1. 사진을 마우스로 눌렀을 때의 시작 좌표 구하기
2. 사진을 마우스로 드래그한 이동 거리만큼 옮기기
- mousemove 좌표- mousedown 좌표 or mouseup 좌표 - mousedown 좌표
- 사진 이동: style.transform = `translateX(${e.clientX - 시작좌표}px)`
3. 마우스를 뗐을 때 드래그한 이동 거리에 따라 보여줄 사진 결정하기
- 사진 보여주기: style.transform = 'translateX(0vw)';
- 끌어당기는 효과 주기: style.transition = 'all 0.5s';
(+) n번째 사진의 이동은 첫 번째 사진에서의 마우스 이동 거리를 계산하여 이동해야 한다!
- style.transform = `translateX(calc(${e.clientX - 시작좌표}px + (-100vw)))`)
Vanilla JS + 축약
let 시작좌표 = 0;
let push = false;
const slideBoxes = document.querySelectorAll('.slide-slide');
const slideContainer = document.querySelector('.slide-container');
for (let i = 0; i < slideBoxes.length; i++) {
const slide = slideBoxes[i];
slide.addEventListener('mousedown', function(e) {
시작좌표 = e.clientX;
push = true;
});
slide.addEventListener('mousemove', function(e) { // 이미지 드래그 효과
if (push) {
const offsetX = i * -100;
slideContainer.style.transform = `translateX(calc(${e.clientX - 시작좌표}px + (${offsetX}vw)))`;
}
});
slide.addEventListener('mouseup', function(e) {
push = false;
let targetIndex; // 이미지 순서 변수 생성
if (e.clientX - 시작좌표 < -100) {
targetIndex = i + 1; // 다음 사진 보여주기
if (targetIndex === slideBoxes.length) { // 마지막 사진은 첫 번째 사진으로 순환
targetIndex = 0;
}
} else if (e.clientX - 시작좌표 > 100) {
targetIndex = i - 1; // 이전 사진 보여주기
if (targetIndex === -1) { // 첫 번째 사진은 마지막 사진으로 순환
targetIndex = slideBoxes.length - 1;
}
} else {
targetIndex = i;
}
// 이미지 이동시키기
const targetTransform = targetIndex * -100;
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = `translateX(${targetTransform}vw)`;
setTimeout(() => { // 애니메이션 렉 제거
slideContainer.style.transition = 'none';
}, 500);
});
}
Vanilla JS
let 시작좌표 = 0;
let push = false; // 마우스 눌렀나 확인하는 변수
// 첫 번째 사진
document.querySelectorAll('.slide-box')[0].addEventListener('mousedown', function(e) {
시작좌표 = e.clientX;
push = true;
});
document.querySelectorAll('.slide-box')[0].addEventListener('mousemove', function(e) {
if (push) {
document.querySelector('.slide-container').style.transform = `translateX(${e.clientX - 시작좌표}px)`;
}
});
document.querySelectorAll('.slide-box')[0].addEventListener('mouseup', function(e) {
push = false;
// 이동 거리 계산 후 -> 기준 사진 or 다음 사진 결정
if (e.clientX - 시작좌표 < -100) { // 다음 사진
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(-100vw)';
} else if (e.clientX - 시작좌표 > 100) { // 왼쪽으로 스와이프 시 이전 사진
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(-200vw)';
} else { // 이전 사진
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(0vw)';
}
setTimeout(() => {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'none';
}, 500);
});
// 두 번째 사진
document.querySelectorAll('.slide-box')[1].addEventListener('mousedown', function(e) {
시작좌표 = e.clientX;
push = true;
});
document.querySelectorAll('.slide-box')[1].addEventListener('mousemove', function(e) {
if (push) {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transform = `translateX(calc(${e.clientX - 시작좌표}px + (-100vw)))`;
}
});
document.querySelectorAll('.slide-box')[1].addEventListener('mouseup', function(e) {
push = false;
if (e.clientX - 시작좌표 < -100) {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(-200vw)';
} else if (e.clientX - 시작좌표 > 100) {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(0vw)';
} else {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(-100vw)';
}
setTimeout(() => {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'none';
}, 500);
});
// 세 번째 사진
document.querySelectorAll('.slide-box')[2].addEventListener('mousedown', function(e) {
시작좌표 = e.clientX;
push = true;
});
document.querySelectorAll('.slide-box')[2].addEventListener('mousemove', function(e) {
if (push) {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transform = `translateX(calc(${e.clientX - 시작좌표}px + (-200vw)))`;
}
});
document.querySelectorAll('.slide-box')[2].addEventListener('mouseup', function(e) {
push = false;
if (e.clientX - 시작좌표 < -100) {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(0vw)';
} else if (e.clientX - 시작좌표 > 100) {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(-100vw)';
} else {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'all 0.5s';
slideContainer.style.transform = 'translateX(-200vw)';
}
setTimeout(() => {
const slideContainer = document.querySelector('.slide-container');
slideContainer.style.transition = 'none';
}, 500);
});
jQuery
var 시작좌표 = 0;
var push = false; // 마우스 눌렀나 확인하는 변수
$('.slide-box').eq(0).on('mousedown', function(e){
시작좌표 = e.clientX;
push = true;
});
$('.slide-box').eq(0).on('mousemove', function(e){
// 마우스 눌렀을 때 움직이도록
if (push == true) {
$('.slide-container').css('transform', `translateX( ${e.clientX - 시작좌표}px )`)
}
});
$('.slide-box').eq(0).on('mouseup', function(e){
// 마우스 떼면 기능 X
push = false;
// 이동 거리 계산 후 -> 기준 사진 or 다음 사진 결정
if (e.clientX - 시작좌표 < -100) {
$('.slide-container') // 다음 사진
.css('transition', 'all 0.5s')
.css('transform', 'translateX(-100vw)');
} else if (e.clientX - 시작좌표 > 100) { // 왼쪽으로 드래그 시 마지막 사진 보여주기
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(-200vw)');
} else {
$('.slide-container') // 기존 사진
.css('transition', 'all 0.5s')
.css('transform', 'translateX(0vw)');
}
setTimeout(() => {
$('.slide-container').css('transition', 'none')
}, 500)
});
//-----------------2번째 사진------------------------
$('.slide-box').eq(1).on('mousedown', function(e){
시작좌표 = e.clientX;
push = true;
});
$('.slide-box').eq(1).on('mousemove', function(e){
if (push == true) {
// 두 번째 사진의 이동은 첫 번째 사진에서의 마우스 이동 거리를 계산하여 이동해야 한다.
$('.slide-container').css('transform', `translateX(calc(${e.clientX - 시작좌표}px + (-100vw)))`)
}
});
$('.slide-box').eq(1).on('mouseup', function(e){
push = false;
if (e.clientX - 시작좌표 < -100) {
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(-200vw)');
} else if (e.clientX - 시작좌표 > 100) { // 왼쪽으로 드래그 시 이전 사진
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(0vw)');
} else {
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(-100vw)');
}
setTimeout(() => {
$('.slide-container').css('transition', 'none')
}, 500)
});
//-----------------3번째 사진------------------------
$('.slide-box').eq(2).on('mousedown', function(e){
시작좌표 = e.clientX;
push = true;
});
$('.slide-box').eq(2).on('mousemove', function(e){
if (push == true) {
// 세 번째 사진의 이동은 첫 번째 사진에서의 마우스 이동 거리를 계산하여 이동해야 한다.
$('.slide-container').css('transform', `translateX(calc(${e.clientX - 시작좌표}px + (-200vw)))`)
}
});
$('.slide-box').eq(2).on('mouseup', function(e){
push = false;
if (e.clientX - 시작좌표 < -100) {
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(0vw)');
} else if (e.clientX - 시작좌표 > 100) { // 왼쪽으로 드래그 시 이전 사진
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(-100vw)');
} else {
$('.slide-container')
.css('transition', 'all 0.5s')
.css('transform', 'translateX(-200vw)');
}
setTimeout(() => {
$('.slide-container').css('transition', 'none')
}, 500)
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC&display=swap');
</style>
<link rel="stylesheet" href="main.css" />
</head>
<body>
<div style="overflow: hidden;">
<div class="slide-container">
<div class="slide-box">
<img src="xiang1.png" draggable="false">
</div>
<div class="slide-box">
<img src="xiang2.png" draggable="false">
</div>
<div class="slide-box">
<img src="xiang3.png" draggable="false">
</div>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
main.css
.slide-container {
width: 300vw;
}
.slide-box {
width: 100vw;
float: left;
}
.slide-box img {
width: 100%;
}
깃허브
https://github.com/kwonboryong/CodingApple/tree/main/carousel-swipe
출처
코딩애플