본문으로 건너뛰기

Cross Flicking

nested 옵션으로 외부(세로) Flicking 안에 내부(가로) Flicking을 중첩하는 2D 크로스 네비게이션을 구성합니다.

import Flicking from "@egjs/flicking";
import "@egjs/flicking/dist/flicking.css";
import "./styles.css";

const GROUPS = [
  { name: "Group A", colors: ["#e74c3c", "#c0392b", "#e67e22"] },
  { name: "Group B", colors: ["#3498db", "#2980b9", "#1abc9c"] },
  { name: "Group C", colors: ["#2ecc71", "#27ae60", "#16a085"] }
];

const outerCamera = document.querySelector("#outer .flicking-camera");

GROUPS.forEach((group, gi) => {
  const outerPanel = document.createElement("div");
  outerPanel.className = "outer-panel";

  const label = document.createElement("div");
  label.className = "group-label";
  label.textContent = `${group.name} (swipe vertically to switch groups)`;
  outerPanel.appendChild(label);

  const innerViewport = document.createElement("div");
  innerViewport.className = "flicking-viewport";
  innerViewport.id = `inner-${gi}`;
  const innerCamera = document.createElement("div");
  innerCamera.className = "flicking-camera";
  innerViewport.appendChild(innerCamera);

  group.colors.forEach((color, pi) => {
    const panel = document.createElement("div");
    panel.className = "inner-panel";
    panel.style.background = color;
    panel.innerHTML = `<span>${group.name}-${pi + 1}</span><span class="panel-subtitle">swipe horizontally</span>`;
    innerCamera.appendChild(panel);
  });

  outerPanel.appendChild(innerViewport);
  outerCamera.appendChild(outerPanel);
});

const outerFlicking = new Flicking("#outer", {
  horizontal: false,
  moveType: "strict",
  bound: true,
  align: "prev"
});

GROUPS.forEach((_, gi) => {
  new Flicking(`#inner-${gi}`, {
    nested: true,
    moveType: "strict",
    bound: true,
    align: "prev"
  });
});

const infoBar = document.querySelector(".info-bar");
outerFlicking.on("changed", e => {
  infoBar.textContent = `Current group: ${GROUPS[e.index].name} (vertical: switch groups / horizontal: navigate within group)`;
});

요약

주요 옵션

옵션위치역할
horizontal외부false세로 방향 (그룹 간 이동)
nested내부true끝 도달 시 외부로 이벤트 전파
moveType양쪽"strict"정확히 1단위씩 이동

구조

구성방향역할
외부 Flicking세로 (↕)그룹 간 이동
내부 Flicking가로 (↔)그룹 내 패널 이동

상세 설명

nested 옵션의 역할

nested: true를 내부 Flicking에 설정하면, 내부 Flicking이 끝에 도달한 후 같은 방향으로 스와이프할 때 이벤트가 외부 Flicking으로 전파됩니다. 이 데모에서는 외부와 내부의 방향이 다르므로(세로/가로) 입력이 자연스럽게 분리됩니다.

방향 분리

가로 스와이프는 내부 Flicking이 처리하고, 세로 스와이프는 외부 Flicking이 처리합니다. 같은 방향 중첩(예: 가로 안에 가로)에서는 nested: true가 이벤트 전파를 관리합니다.

연관 옵션

  • nestedhorizontal의 관계: 서로 다른 방향이면 충돌 없이 동작, 같은 방향이면 nested: true로 전파 제어
  • moveType: "strict"와의 조합: 그룹/패널 단위 이동이 명확해짐
  • bound: true와의 조합: 각 레벨에서 빈 공간 방지

사용 시나리오

언제 사용하나요?
  • 카테고리별 콘텐츠 (세로로 카테고리, 가로로 항목)
  • 사진 앨범 (세로로 앨범, 가로로 사진)
  • 대시보드 (세로로 섹션, 가로로 카드)

주의사항

주의
  • 외부 Flicking이 세로(horizontal: false)일 때, 반드시 뷰포트에 높이를 지정해야 합니다.
  • 내부 Flicking에 nested: true를 설정하지 않으면, 내부에서 이벤트가 소비되어 외부로 전파되지 않습니다.
  • 같은 방향으로 중첩할 경우 스와이프 제스처 구분이 어려울 수 있습니다.

관련 링크

관련 옵션

관련 데모