[๐Ÿšจ Error ๐Ÿšจ] DnD + Carousel ์ถฉ๋Œ

์šฐํ˜ยท2024๋…„ 4์›” 25์ผ

๐Ÿšจ Error ๐Ÿšจ

๋ชฉ๋ก ๋ณด๊ธฐ
7/11

๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ๋ฐฐ๊ฒฝ

ํ”„๋กœ์ ํŠธ์— DnD + Carousel์„ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ณผ์ •์—์„œ ํ•ญ๋ชฉ์„ ๋“œ๋ž˜๊ทธํ•˜๋ฉด์„œ ์˜†์œผ๋กœ ์ด๋™ํ•˜๋Š”๊ฒŒ ์•ˆ๋˜๋Š” ์ƒํ™ฉ

  • ๋ฌธ์ œ ์ƒํ™ฉ

๋ฌธ์ œ์˜ ์›์ธ ์•Œ์•„๋ณด๊ธฐ

์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋ฉด์„œ ์›์ธ์„ ํŒŒ์•…ํ•˜์˜€๋Š”๋ฐ Carousel์˜ ์Šค๋ƒ… ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์˜€๋‹ค.

  • ์Šค๋ƒ… ๊ธฐ๋Šฅ์ด๋ž€?
    ์‚ฌ์šฉ์ž๊ฐ€ ์บ๋Ÿฌ์…€์„ ์Šฌ๋ผ์ด๋“œํ•  ๋•Œ, ๊ฐ ์Šฌ๋ผ์ด๋“œ๊ฐ€ ํ™”๋ฉด์— ์ •ํ™•ํžˆ ๋งž์ถฐ์ ธ ๋ณด์ด๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋งํ•œ๋‹ค.
  • CSS ์ฝ”๋“œ
.wrap {
  display: flex;
  gap: 40px;
  overflow-x: auto;
  scroll-behavior: smooth; // ์Šคํฌ๋กค ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์„ค์ •
  scroll-snap-type: x mandatory; // ๊ฐ€๋กœ ์Šคํฌ๋กค ๋™์ž‘ ์Šค๋ƒ… ์„ค์ •
  scrollbar-width: none;
}

.box {
  width: 780px;
  min-height: 800px;
  border: 1px solid #000;
  display: flex;
  flex-direction: column;
  gap: 10px;
  scroll-snap-align: start; // ์Šคํฌ๋กค ์ง€์  ์ •๋ ฌ
}

์Šค๋ƒ… ๊ธฐ๋Šฅ์„ ์ œ๊ฑฐ ํ•ด์ฃผ๋ฉด ์ด์ œ ์˜†์œผ๋กœ ์ด๋™์„ ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ต‰์žฅํžˆ ๋‹ต๋‹ตํ•œ ์†๋„๋กœ ์ด๋™์„ ํ•œ๋‹ค.

์ด ๋ฌธ์ œ๋„ ์Šคํฌ๋กค์„ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ํ•ด์ฃผ๋Š” ์„ค์ •์„ ์ œ๊ฑฐ ํ•ด์ฃผ๋ฉด ์ •์ƒ์ ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค!


๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์‚ฌ์‹ค ์œ„์— ๋ฐฉ๋ฒ•์œผ๋กœ ์Šค๋ƒ… ๊ธฐ๋Šฅ, ์Šคํฌ๋กค ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ํ•ด์ฃผ๋Š” ์„ค์ •์„ ์ œ๊ฑฐํ•˜์—ฌ ์˜†์œผ๋กœ ์ด๋™ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ด์Šˆ๋Š” ํ•ด๊ฒฐํ•˜์˜€์ง€๋งŒ ์Šค๋ƒ… ๊ธฐ๋Šฅ CSS ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•ด์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด๊ฐ€ ์ง์ ‘ ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋กœ ์Šค๋ƒ… ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค...

ํ˜„์žฌ ์ƒํ™ฉ

  • ์œ ์ €๊ฐ€ ๋งˆ์šฐ์Šค๋กœ ์Šค์™€์ดํ”„ ํ•œ ๋งŒํผ๋งŒ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์Šค๋ƒ… ๊ธฐ๋Šฅ์ด ์‚ฌ๋ผ์ ธ ๋”ฑ ๋งž๊ฒŒ ์Šค์™€์ดํ”„ ๋˜์ง€ ์•Š๋Š”๋‹ค.

์‚ฌ์‹ค ํŒ€์›๋ถ„์ด ์ง€๊ธˆ ๋ฐฉ์‹๋„ ๊ดœ์ฐฎ๋‹ค๊ณ  ๋ง์”€ํ•ด์ฃผ์…จ์ง€๋งŒ ์˜†์œผ๋กœ ํ•ญ๋ชฉ์ด ๋งŽ๊ณ  ๋ชจ๋‹ˆํ„ฐ๊ฐ€ ์ž‘์œผ๋ฉด ๊ทธ๋งŒํผ ์œ ์ €๊ฐ€ ๋™์ž‘์‹œ์ผœ์•ผ ํ•  ์ด๋ฒคํŠธ๊ฐ€ ๋งŽ์•„์ ธ ๋งˆ์Œ์— ๋“ค์ง€์•Š์•„ ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋กœ ์Šค๋ƒ… ๊ธฐ๋Šฅ์„ ๋น„์Šทํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค!

๋ฐ•์Šค ํฌ๊ธฐ๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ์ขŒ/์šฐ ์Šค์™€์ดํ”„๋งŒ ๊ตฌ๋ถ„ํ•ด์„œ ๊ทธ๋งŒํผ ์Šคํฌ๋กค์„ ์ด๋™์‹œ์ผœ์ฃผ๋ฉด ์Šค๋ƒ… ๊ธฐ๋Šฅ๊ณผ ๊ฐ™์€ ๋™์ž‘์„ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

  • ๊ตฌํ˜„ ์ฝ”๋“œ
  const handlePrevCard = () => {
    cardContainer.current.scrollBy({
      left: -820, // ๋ฐ•์Šค ํฌ๊ธฐ ๊ณ„์‚ฐ
      top: 0,
      behavior: "smooth",
    });
  };

  const handleNextCard = () => {
    cardContainer.current.scrollBy({
      left: 820, // ๋ฐ•์Šค ํฌ๊ธฐ ๊ณ„์‚ฐ
      top: 0,
      behavior: "smooth",
    });
  };

const handleSwipeAction = (xDiff: any) => {
    if (xDiff > 0) { //์šฐ์ธก ์ด๋™
      handleNextCard();
      return;
    }
    // ์ขŒ์ธก ์ด๋™
    handlePrevCard();
  };

  const handleMove = () => {
    if (!xDown.current) {
      return;
    }
    const xDiff = xDown.current - xUp.current;
    if (xDiff !== 0) {
      handleSwipeAction(xDiff);
    }
    // ์ขŒํ‘œ ์ดˆ๊ธฐํ™”
    xDown.current = null;
    xUp.current = null;
  };

  // ๋งˆ์šฐ์Šค ๋ˆ„๋ฅผ ๋•Œ ๋™์ž‘
  const handleMouseDown = (e: MouseEvent) => {
    const target = e.target as HTMLElement;
    if (target.dataset.status === "item") {
      return;
    }

    xDown.current = e.clientX;
    document.body.style.userSelect = "none";
  };

  // ๋งˆ์šฐ์Šค ๋—„ ๋•Œ ๋™์ž‘
  const handleMouseUp = (e: MouseEvent) => {
    xUp.current = e.clientX;
    handleMove();
    document.body.style.userSelect = "";
  };
  • ๊ตฌํ˜„ ์˜์ƒ

์ด์ „ ๋ฐฉ์‹์— ๋น„ํ•ด ์Šค์™€์ดํ”„ ํ–ˆ์„ ๋•Œ ์ผ๊ด€์„ฑ์žˆ๋Š” UI๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


์ตœ์ข… ๋™์ž‘ ์˜์ƒ

์กฐ๊ธˆ ๋” ์œ ์ €์—๊ฒŒ ์ข‹์€ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜์—ฌ UX๋ฅผ ๊ฐœ์„ ํ•˜๊ณ  ์‹ถ์–ด์„œ ์ขŒ/์šฐ ๋ฒ„ํŠผ๋„ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€