์๋ฐ์คํฌ๋ฆฝํธ : ๋ง์ฐ์ค ํจ๊ณผ : ๋ง์ฐ์ค ๋ฐ๋ผ๋ค๋๊ธฐ(GSAP)
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ค์ํ ํจ๊ณผ๋ค ์ค, ๋ง์ฐ์ค ํจ๊ณผ์ ๋๋ค. ์ด๋ฒ์๋ GSAP๋ฅผ ํ์ฉํ์ฌ ๋ ๋ถ๋๋ฝ๊ฒ ์์ง์ด๋ ์ปค์๋ฅผ ์์ ํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. HTML ์์ค
<section id="mouseType02">
<div class="mouse__cursor"></div>
<div class="mouse__cursor2"></div>
<div class="mouse__wrap">
<p>Only <span class="style1">I can change</span> my life, <span class="style2">No one can</span> do it <span class="style3">for me</span></p>
<p><span class="style4">์ค์ง ๋๋ง์ด</span> ๋ด ์ธ์์ <span class="style5">๋ฐ๊ฟ ์ ์๋ค.</span> <span class="style6">์๋ฌด๋</span> ๋ ๋์ ํ ์๋ ์๋ค</p>
</div>
</section>
์ด๋ฒ์๋ ์ปค์๋ฅผ ๋ ๊ฐ ์์ ํด ์ฃผ์์ต๋๋ค. HTML๋ก ๊ตฌ์กฐ๋ฅผ ์ก์ ํ, CSS๋ก ์คํ์ผ์ ์ ์ฉํด ์ค๋๋ค.
2. CSS ์์ค
.mouse__wrap {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
overflow: hidden;
flex-direction: column;
/* cursor: none; */
}
.mouse__wrap p {
font-size: 2vw;
line-height: 2;
font-weight: 300;
}
.mouse__wrap p:last-child {
font-size: 3vw;
}
.mouse__wrap p span {
border-bottom: 0.35vw dashed rgb(77, 46, 128);
color: rgb(77, 46, 128);
}
@media (max-width: 800px) {
.mouse__wrap p {
font-size: 20px;
padding: 0 20px;
text-align: center;
line-height: 1.5;
word-break: keep-all;
margin-bottom: 10px;
}
.mouse__wrap p:last-child {
font-size: 40px;
}
}
.mouse__cursor {
position: absolute;
left: 0;
top: 0;
width: 10px;
height: 10px;
z-index: 9999;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
user-select: none;
pointer-events: none;
transition: transform 0.3s, opacity 0.2s;
}
.mouse__cursor2 {
position: absolute;
left: 0;
top: 0;
width: 30px;
height: 30px;
z-index: 9998;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
user-select: none;
pointer-events: none;
transition: transform 0.3s, opacity 0.2s;
}
.mouse__cursor.menuactive {
transform: scale(0);
}
.mouse__cursor2.menuactive {
transform: scale(2) rotate(720deg);
background: rgba(164, 123, 22, 0.6);
border-radius: 0;
}
.mouse__cursor.active {
transform: scale(0);
}
.mouse__cursor2.active {
transform: scale(10);
background: rgba(77, 46, 128, 0.6);
}
.mouse__cursor.sourceactive {
transform: scale(0);
}
.mouse__cursor2.sourceactive {
transform: scaleX(3);
background: rgba(240, 92, 92, 0.6);
}
์ฒซ๋ฒ์งธ ์ปค์๋ ์์ ๋๊ทธ๋ผ๋ฏธ, ๋๋ฒ์งธ ์ปค์๋ ํฐ ๋๊ทธ๋ผ๋ฏธ๋ก ์คํ์ผ์ ์ ์ฉํด ์ฃผ์์ต๋๋ค. ์ปค์๊ฐ ํค๋์ ๋ฉ๋ด์ ์์นํ์ ๋, ๋ช ์ธ์ span ํ๊ทธ ์์ ์์นํ์ ๋, ํธํฐ์ ์์ค ๋ณด๊ธฐ ๋ฒํผ์ ์์นํ์ ๋ 3๊ฐ์ง ๋ชจ์์ผ๋ก ๋ณํ๋ ์ ์๋๋ก menuactive, active, sourceactive ํด๋์ค๋ฅผ ๊ฐ๊ฐ ์์ ํด ์ฃผ์์ต๋๋ค.
3. JAVASCRIPT ์์ค
3-1) ์ ํ์ ๋ง๋ค์ด ์ฃผ๊ธฐ
const cursor = document.querySelector(".mouse__cursor");
const cursor2 = document.querySelector(".mouse__cursor2");
const menu = document.querySelectorAll("#header ul li");
const span = document.querySelectorAll(".mouse__wrap span");
const sourceBtn = document.querySelectorAll(".modal__btn");
๋ง์ฐ์ค ์ปค์, ๋ฉ๋ด, ๋ช ์ธ, ์์ค ๋ณด๊ธฐ ๋ฒํผ์ ๋ํ ์ ํ์๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
3-2) ๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ ๋ง๋ค์ด ์ฃผ๊ธฐ
window.addEventListener("mousemove", (e) => {});
์ด์ addEventListener๋ฅผ ์ด์ฉํ์ฌ ๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ๋ฅผ ๋ง๋ค์ด ์ค๋๋ค. ์๋ ์์ค๋ค์ ๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ ์์์ ์์ ํ ์์ค๋ค์ ๋๋ค.
// ์ปค์ ์ขํ๊ฐ ํ ๋น
// cursor.style.left = e.pageX - 5 + "px";
// cursor.style.top = e.pageY - 5 + "px";
// cursor2.style.left = e.pageX - 15 + "px";
// cursor2.style.top = e.pageY - 15 + "px";
// GSAP
gsap.to(cursor, { duration: 0.3, left: e.pageX - 5, top: e.pageY - 5 });
gsap.to(cursor2, { duration: 0.8, left: e.pageX - 15, top: e.pageY - 15 });
์์ ๋ฐฉ๋ฒ์ผ๋ก ์ง์ ์ปค์ ์ขํ๊ฐ์ ํ ๋นํ ์๋ ์์ง๋ง, ๋ ๋ถ๋๋ฌ์ด ์์ง์์ ์ํ์ฌ GSAP๋ฅผ ์ด์ฉํ์ต๋๋ค. GSAP๋ฅผ ์ฌ์ฉํ ๋๋ ์คํฌ๋ฆฝํธ ๋งํฌ๋ฅผ ๊ผญ ๊ฑธ์ด ์ค์๋ค.
// ๋ฉ๋ด์ ์ปค์๋ฅผ ์ค๋ฒํ์ ๋
menu.forEach((menu) => {
menu.addEventListener("mouseenter", () => {
cursor.classList.add("menuactive");
cursor2.classList.add("menuactive");
});
menu.addEventListener("mouseleave", () => {
cursor.classList.remove("menuactive");
cursor2.classList.remove("menuactive");
});
});
// ์ฝํ
์ธ ์ ์ปค์๋ฅผ ์ค๋ฒํ์ ๋
span.forEach((span) => {
span.addEventListener("mouseenter", () => {
cursor.classList.add("active");
cursor2.classList.add("active");
});
span.addEventListener("mouseleave", () => {
cursor.classList.remove("active");
cursor2.classList.remove("active");
});
});
// ์์ค ๋ณด๊ธฐ ๋ฒํผ์ ์ปค์๋ฅผ ์ค๋ฒํ์ ๋
sourceBtn.forEach((source) => {
source.addEventListener("mouseenter", () => {
cursor.classList.add("sourceactive");
cursor2.classList.add("sourceactive");
});
source.addEventListener("mouseleave", () => {
cursor.classList.remove("sourceactive");
cursor2.classList.remove("sourceactive");
});
});
๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ ๋ฉ์๋๋ mouseenter, mouseover ๋ ๊ฐ์ง๊ฐ ์์ง๋ง, mouseenter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์
ํด ๋ณด์์ต๋๋ค.
๋ ๋ฉ์๋์ ์ฐจ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ : ๋ง์ฐ์ค ์ด๋ฒคํธ ๋ฉ์๋ : mouseover VS mouseenter๋ฅผ ์ฐธ๊ณ ํด
์ฃผ์ธ์.
๋ฉ๋ด ๋ฒํผ, ๋ช
์ธ, ์์ค ๋ณด๊ธฐ ๋ฒํผ ๊ฐ๊ฐ์ ์ปค์๋ฅผ ์์นํ์ ๋, ๊ฐ๊ฐ์ ํด๋นํ๋ active ํด๋์ค๋ฅผ ์ถ๊ฐํด ์ฃผ๊ณ ,
์ปค์์ ์์น๊ฐ ๋ฒ์ด๋๋ฉด active ํด๋์ค๋ฅผ ์ ๊ฑฐํ๋๋ก ์์
ํด ์ค๋๋ค.
๊ฒฐ๊ณผ
'Javascript Effect' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์๋ฐ์คํฌ๋ฆฝํธ ๋ง์ฐ์ค ํจ๊ณผ : ์กฐ๋ช ํจ๊ณผ (9) | 2022.09.22 |
---|---|
์๋ฐ์คํฌ๋ฆฝํธ ํจ๋ด๋์ค ํจ๊ณผ : ์ด์ง๊ฐ ํจ๊ณผ (5) | 2022.09.20 |
์๋ฐ์คํฌ๋ฆฝํธ ์ฌ๋ผ์ด๋ ํจ๊ณผ : ๋ฒํผ (3) | 2022.09.18 |
์๋ฐ์คํฌ๋ฆฝํธ ํจ๋ด๋์ค ํจ๊ณผ : ๋ํ๋๊ธฐ (4) | 2022.09.18 |
์๋ฐ์คํฌ๋ฆฝํธ ํจ๋ด๋์ค ํจ๊ณผ : ๋ฉ๋ด ์จ๊น, TOP๋ฒํผ (6) | 2022.09.10 |
๋๊ธ