반응형
커스텀 커서와 프리로더를 사용한 홀드 트리거 인터랙션 만들기
이 블로그 포스트에서는 커스텀 커서와 프리로더 버튼을 사용하여 홀드 트리거 인터랙션을 만드는 과정을 안내합니다. 이 인터랙션은 버튼을 눌러 확인하거나 기능을 잠금 해제하는 등의 시나리오에서 유용합니다. HTML, CSS 및 JavaScript를 사용하여 이 효과를 달성할 것입니다.
HTML 구조
먼저 기본 HTML 구조를 설정합니다. 커스텀 커서와 프리로더 섹션이 버튼으로 사용됩니다.
<div class="cursor">
<div class="cursor__default">
<span class="cursor__default__inner"></span>
</div>
<div class="cursor__trace">
<span class="cursor__trace__inner"></span>
</div>
</div>
<section class="preloader shown-area">
<button class="preloader__btn">
<span class="preloader__btn_hold"></span>
</button>
</section>
<section class="header hidden-area">
Header
</section>
CSS 스타일링
다음으로, 요소들을 스타일링합니다. 커서는 마우스 움직임을 따라가고, 프리로더 버튼은 눌린 상태에서 확대됩니다.
body {
cursor: none !important;
background-color: #1e4029;
}
.shown-area {
display: block;
opacity: 1;
}
.hidden-area {
display: none;
opacity: 0;
}
.cursor {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
pointer-events: none !important;
}
.cursor__default__inner {
position: absolute;
display: inline-block;
width: 20px;
height: 20px;
background-color: rgba(10, 27, 16, 2.5);
border: 2px solid #d5a54e;
border-radius: 50%;
transform: translate(-50%, -50%);
}
.cursor__trace__inner {
position: absolute;
display: inline-block;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: rgba(0, 0, 0, .25);
transform: translate(-50%, -50%);
transition: all .04s ease;
}
.cursor--active .cursor__trace__inner {
transform: scale(0.5) translate(-100%, -100%);
transition: transform .3s ease;
}
@keyframes ripple {
0% {
transform: scale(0);
opacity: 1;
}
20% {
transform: scale(5);
opacity: 1;
}
100% {
transform: scale(10);
opacity: 0;
}
}
.ripple {
position: absolute;
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #d5a54e;
animation: ripple .5s ease-out;
animation-fill-mode: forwards;
z-index: -1;
}
.preloader {
position: absolute;
top: 0;
left: 0;
background-color: #000000;
width: 100%;
height: 100%;
z-index: 999;
}
.preloader__btn {
position: absolute;
top: 50vh;
left: 50vw;
width: 120px;
height: 120px;
border-radius: 50%;
border: none;
color: rgb(213, 165, 78);
background: url('https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba?q=80&w=2886&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D');
background-size: cover;
margin-top: -60px;
margin-left: -60px;
}
.preloader__btn_hold {
font-size: 19px;
line-height: 20px;
font-weight: 800;
letter-spacing: normal;
}
인터랙션을 위한 JavaScript
마지막으로, 커서 움직임, 버튼 스케일링, 홀드 트리거 인터랙션을 처리하는 JavaScript를 추가합니다.
// Handle cursor movement for both mouse and touch events
function moveCursor(e) {
const cursorDefaultInner = document.querySelector(".cursor__default__inner");
const cursorTraceInner = document.querySelector(".cursor__trace__inner");
const clientX = e.clientX || (e.touches && e.touches[0].clientX);
const clientY = e.clientY || (e.touches && e.touches[0].clientY);
cursorDefaultInner.style.top = clientY + "px";
cursorDefaultInner.style.left = clientX + "px";
cursorTraceInner.style.top = clientY + "px";
cursorTraceInner.style.left = clientX + "px";
}
document.addEventListener("mousemove", moveCursor);
document.addEventListener("touchmove", moveCursor);
const cursor = document.querySelector(".cursor");
// Handle cursor active state for both mouse and touch events
function activateCursor() {
cursor.classList.add("cursor--active");
}
function deactivateCursor() {
cursor.classList.remove("cursor--active");
}
document.addEventListener("mousedown", activateCursor);
document.addEventListener("touchstart", activateCursor);
document.addEventListener("mouseup", deactivateCursor);
document.addEventListener("touchend", deactivateCursor);
document.addEventListener("touchcancel", deactivateCursor);
// Create ripple effect for both mouse and touch events
function createRipple(e) {
const clientX = e.clientX || (e.touches && e.touches[0].clientX);
const clientY = e.clientY || (e.touches && e.touches[0].clientY);
let ripple = document.createElement("span");
ripple.classList.add("ripple");
cursor.appendChild(ripple);
ripple.style.top = clientY - ripple.clientHeight / 2 + "px";
ripple.style.left = clientX - ripple.clientWidth / 2 + "px";
ripple.addEventListener("animationend", () => {
cursor.removeChild(ripple);
});
}
document.addEventListener("click", createRipple);
document.addEventListener("touchstart", (e) => {
createRipple(e);
// Prevent the default touch event to avoid issues with click handling
e.preventDefault();
});
const preloaderBtn = document.querySelector(".preloader__btn");
let scale = 1;
let intervalId = null;
const preloaderHideThreshold = 18;
const preloaderHideGap = 0.175;
// Handle preloader button scaling for both mouse and touch events
function startScaling() {
clearInterval(intervalId);
intervalId = setInterval(() => {
scale += preloaderHideGap;
console.log(scale);
preloaderBtn.style.transform = `scale(${scale})`;
if (scale >= preloaderHideThreshold) {
alert("meow");
clearInterval(intervalId);
scale = 1;
}
}, 10);
}
function stopScaling() {
clearInterval(intervalId);
intervalId = setInterval(() => {
scale -= preloaderHideGap;
console.log(scale);
preloaderBtn.style.transform = `scale(${scale})`;
if (scale <= 1) {
clearInterval(intervalId);
scale = 1;
}
}, 10);
}
preloaderBtn.addEventListener("mousedown", startScaling);
preloaderBtn.addEventListener("touchstart", (e) => {
startScaling();
// Prevent the default touch event to avoid issues with click handling
e.preventDefault();
});
preloaderBtn.addEventListener("mouseup", stopScaling);
preloaderBtn.addEventListener("touchend", stopScaling);
preloaderBtn.addEventListener("touchcancel", stopScaling);
설명
- 커스텀 커서: 마우스 움직임을 따라가는 커스텀 커서를 생성합니다. 커서는 기본 내부 커서와 추적 커서의 두 부분으로 구성됩니다.
- 커서 리플 효과: 클릭 시 커서 위치에서 리플 효과가 생성되어 시각적 피드백을 제공합니다.
- 프리로더 버튼: 프리로더 버튼은 눌린 상태에서 점차 확대됩니다. 버튼이 충분히 오래 눌리면(
preloaderHideThreshold
로 정의됨) 경고 창이 표시됩니다. - 버튼 스케일링: 버튼이 눌린 동안 점차 확대되고, 마우스를 놓으면 다시 축소됩니다.
이 접근 방식은 시각적으로 매력적이고 인터랙티브한 홀드 트리거 버튼을 커스텀 커서 효과와 함께 제공합니다. 스타일과 인터랙션을 쉽게 사용자 맞춤화하여 특정 요구에 맞출 수 있습니다.
반응형
'UX 개발 > UX - 커서 & 클릭 & 키보드' 카테고리의 다른 글
마우스에 따라 반대로 움직이는 HTML 요소 만들기 (0) | 2024.07.17 |
---|---|
HTML, CSS, JavaScript로 커서를 간단히 커스터마이징하기 (0) | 2024.07.07 |