๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Javascript Effect

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋งˆ์šฐ์Šค ํšจ๊ณผ : ํ…์ŠคํŠธ ํšจ๊ณผ

by ์ฝ”ํŒŒ์นด 2022. 9. 29.
728x90

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ : ๋งˆ์šฐ์Šค ํšจ๊ณผ : ํ…์ŠคํŠธ ํšจ๊ณผ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋‹ค์–‘ํ•œ ํšจ๊ณผ๋“ค ์ค‘, ๋งˆ์šฐ์Šค ํšจ๊ณผ์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ์ด๋ฏธ์ง€ ์œ„์— ๊ธฐ์šธ์–ด์ง„ ํ˜•ํƒœ์˜ ํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ๋งˆ์šฐ์Šค๋ฅผ ์›€์ง์ผ ๋•Œ๋งˆ๋‹ค ํ…์ŠคํŠธ๊ฐ€ ์›€์ง์ด๋„๋ก ํ…์ŠคํŠธ ํšจ๊ณผ๋ฅผ ์ž‘์—…ํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


1. HTML ์†Œ์Šค

1-1) ํ…์ŠคํŠธ ์ƒ์ž ๋งŒ๋“ค๊ธฐ

<div class="mouse__text">
    <div class="line">
        <div class="left">
            <div class="spanWrap">
                <span class="spanSlow">Pain Fast</span>
            </div>
        </div>
        <div class="right">
            <div class="spanWrap">
                <span class="spanSlow">Pain Fast</span>
            </div>
        </div>
    </div>
    <div class="line">
        <div class="left">
            <div class="spanWrap">
                <span class="spanFast">is pleasure.</span>
            </div>
        </div>
        <div class="right">
            <div class="spanWrap">
                <span class="spanFast">is pleasure.</span>
            </div>
        </div>
    </div>
    <div class="line">
        <div class="left">
            <div class="spanWrap">
                <span class="spanSlow">์ง€๋‚˜๊ฐ„ ๊ณ ํ†ต์€</span>
            </div>
        </div>
        <div class="right">
            <div class="spanWrap">
                <span class="spanSlow">์ง€๋‚˜๊ฐ„ ๊ณ ํ†ต์€</span>
            </div>
        </div>
    </div>
    <div class="line">
        <div class="left">
            <div class="spanWrap">
                <span class="spanFast">์พŒ๋ฝ์ด๋‹ค.</span>
            </div>
        </div>
        <div class="right">
            <div class="spanWrap">
                <span class="spanFast">์พŒ๋ฝ์ด๋‹ค.</span>
            </div>
        </div>
    </div>
</div>

์˜ค๋Š˜์€ HTML์˜ ๊ตฌ์กฐ๋„ ์ค‘์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ•จ๊ป˜ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ…์ŠคํŠธ ์ƒ์ž๋Š” ํ•˜๋‚˜์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ์‚ฌ์‹ค์€ ๋‹ค๋ฅธ ๊ฐ๋„๋กœ ๊ธฐ์šธ์–ด์ง„ ๋‘ ๊ฐœ์˜ ์ƒ์ž๊ฐ€ ์žˆ๊ณ , ๋‘ ์ƒ์ž๊ฐ€ ๋งŒ๋‚˜๋Š” ์ง€์  ์ดํ›„๋กœ๋Š” overflow: hidden ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆจ๊ฒจ์ค€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ๋„ค ์ค„์˜ ํ…์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— line ๋ฐ•์Šค๋ฅผ ๋„ค ๊ฐœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๊ทธ ์•ˆ์—๋Š” ๊ฐ๊ฐ left, right ๋ฐ•์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๊ทธ ์•ˆ์— span์œผ๋กœ ํ…์ŠคํŠธ๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

2. CSS ์†Œ์Šค

2-1) text box

.mouse__text .line {
    width: 100%;
    display: flex;
}
.mouse__text .line .left {
    width: 50vw;
    color: orange;
    overflow: hidden;
    transform: skew(0deg, -15deg);
}
.mouse__text .line .left .spanWrap {
    width: 100vw;
    text-align: center;
}
.mouse__text .line .right {
    width: 50vw;
    overflow: hidden;
    transform: skew(0deg, 15deg);
}
.mouse__text .line .right .spanWrap {
    width: 100vw;
    text-align: center;
    transform: translateX(-50vw);
}
.mouse__text span {
    display: inline-block;
}

ํ…์ŠคํŠธ ์ƒ์ž๋“ค์„ ๋งŒ๋“ค์—ˆ๋‹ค๋ฉด CSS ์†์„ฑ์„ ์ ์šฉํ•ด ์ค๋‹ˆ๋‹ค.
transform: skew ์†์„ฑ์€ ์š”์†Œ์˜ ๊ฒฝ์‚ฌ๋ฅผ ๋ณ€ํ˜•์‹œํ‚ฌ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. left, right ๋ฐ•์Šค์— ๊ฐ๊ฐ ์ ์šฉ์‹œ์ผœ ์ค๋‹ˆ๋‹ค. ์š”์†Œ๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ๋ถ€๋ถ„์€ overflow: hidden์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆจ๊ฒจ์ค๋‹ˆ๋‹ค.

2-2) cursor

.mouse__cursor {
    position: absolute;
    left: 0;
    top: 0;
    width: 20px;
    height: 20px;
    z-index: 9999;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.9);
    user-select: none;
    pointer-events: none;
    mix-blend-mode: difference;
    transition: transform 0.3s;
}
.mouse__cursor.active {
    transform: scale(5);
}

๋งˆ์šฐ์Šค ์ปค์„œ์—๋„ ์Šคํƒ€์ผ์„ ์ ์šฉํ•ด ์ค๋‹ˆ๋‹ค. ํฌ๊ธฐ๊ฐ€ 20px์ธ ์› ๋ชจ์–‘์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๊ณ , mix-blend-mode: difference ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ค๋ฒ„ํ–ˆ์„ ๋•Œ ์ƒ‰์ƒ์ด ๋ณ€ํ™”ํ•˜๋Š” ๋ฐ˜์ „ ํšจ๊ณผ๋„ ๋ถ€์—ฌํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. active ํด๋ž˜์Šค๋Š” ํ…์ŠคํŠธ ์œ„์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ค๋ฒ„ํ–ˆ์„ ๋•Œ, ๋ฐ˜์ „ ํšจ๊ณผ๊ฐ€ ๋” ์ž˜ ๋‚˜ํƒ€๋‚˜๊ฒŒ๋” ํฌ๊ธฐ๋ฅผ 5๋ฐฐ ํ‚ค์šฐ๊ธฐ ์œ„ํ•ด ์ž‘์—…ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

3. JAVASCRIPT ์†Œ์Šค

3-1) mousemove ์ด๋ฒคํŠธ ๋งŒ๋“ค๊ธฐ

const mouseMove = (e) => {
    let positionSlow = (e.pageX - window.innerWidth / 2) * 0.1;
    let positionFast = (e.pageX - window.innerWidth / 2) * 0.2;

    gsap.to(".spanSlow", { duration: 0.4, x: positionSlow });
    gsap.to(".spanFast", { duration: 0.4, x: positionFast });
    gsap.to(".mouse__cursor", { duration: 0.3, left: e.pageX - 10, top: e.pageY - 10 });
};
window.addEventListener("mousemove", mouseMove);

๋จผ์ €, mousemove ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. positionSlow, positionFast ๋ณ€์ˆ˜๋Š” ์ด๋ฏธ์ง€์˜ ์›€์ง์ž„ ์ •๋„๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ํ…์ŠคํŠธ๊ฐ€ ์ด๋ฏธ์ง€ ์˜์—ญ์„ ๋ฒ—์–ด๋‚˜์ง€ ์•Š๋„๋ก, window.innerWidth / 2๋งŒํผ์„ ๋นผ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. Slow๋Š” ์‚ด์ง ๋Š๋ฆฌ๊ฒŒ, Fast๋Š” ์‚ด์ง ๋น ๋ฅด๊ฒŒ ์›€์ง์ด๋„๋ก ๊ฐ๊ฐ 0.1, 0.2๋ฅผ ๊ณฑํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
์ดํ›„, gsap๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์›€์ง์ด๋„๋ก ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๋งˆ์šฐ์Šค ์ปค์„œ์˜ ์›€์ง์ž„๋„ ํ•จ๊ป˜ ์ž‘์—…ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. 10์„ ๋นผ๋Š” ์ด์œ ๋Š” ๋งˆ์šฐ์Šค ์ปค์„œ์˜ ํฌ๊ธฐ๊ฐ€ 20px, 20px์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

3-2) mouseenter ์ด๋ฒคํŠธ ๋งŒ๋“ค๊ธฐ

const text = document.querySelectorAll(".spanSlow");
const text2 = document.querySelectorAll(".spanFast");

์ด์ œ ํ…์ŠคํŠธ ์œ„์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ค๋ฒ„ํ•˜๋ฉด ๋งˆ์šฐ์Šค๊ฐ€ ์ปค์ง€๋„๋ก ์ž‘์—…ํ•ด ๋ด…์‹œ๋‹ค. ๊ฐ๊ฐ์˜ ํ…์ŠคํŠธ๋ฅผ ๋จผ์ € ์„ ํƒํ•ด ์ค๋‹ˆ๋‹ค. spanSlow, spanFast๋Š” ๊ฐ๊ฐ 4๊ฐœ์”ฉ ์กด์žฌํ•˜๋ฏ€๋กœ, querySelectorAll์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

text.forEach((e) => {
    e.addEventListener("mouseenter", () => {
        document.querySelector(".mouse__cursor").classList.add("active");
    });
    e.addEventListener("mouseleave", () => {
        document.querySelector(".mouse__cursor").classList.remove("active");
    });
});
text2.forEach((e) => {
    e.addEventListener("mouseenter", () => {
        document.querySelector(".mouse__cursor").classList.add("active");
    });
    e.addEventListener("mouseleave", () => {
        document.querySelector(".mouse__cursor").classList.remove("active");
    });
});

querySelectorAll์„ ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, forEach๋ฌธ์œผ๋กœ ์ž‘์—…ํ•ด ์ค๋‹ˆ๋‹ค. text๋ฅผ ๊ฐ๊ฐ ์„ ํƒํ•˜๊ณ , addEventListener๋กœ mouseenter, mouseleave ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.
๋งˆ์šฐ์Šค๊ฐ€ ํ…์ŠคํŠธ ์œ„์— ์œ„์น˜ํ–ˆ์„ ๋•Œ(mouseenter)๋Š” ์ปค์„œ์— active(transform: scale(5)) ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ๊ณ ,
๋งˆ์šฐ์Šค๊ฐ€ ํ…์ŠคํŠธ๋ฅผ ๋ฒ—์–ด๋‚ฌ์„ ๋•Œ(mouseleave)๋Š” ์ปค์„œ์— active ํด๋ž˜์Šค๋ฅผ ์ œ๊ฑฐํ•ด ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.


๊ฒฐ๊ณผ

728x90

๋Œ“๊ธ€

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๐Ÿฆ™

CSS
๊ด‘๊ณ  ์ค€๋น„์ค‘