문서/API

모디파이어와 충돌 감지

드래그 중인 항목이 갈 위치를 바꾸는 함수와, 그 아래의 대상을 고르는 함수.

이 페이지 편집

이 페이지는 AI가 번역했으며 부정확한 내용이 있을 수 있습니다. 영어 원문 읽기

Live

데모 불러오는 중…

<script setup lang="ts">
import { ref } from 'vue';
import { DnDProvider, closestCenter, closestCorners, pointerFirst, pointerWithin, rectIntersection } from '@vue-dnd-kit/core';
import ModifierLab from './ModifierLab.vue';

// Collision detection is the provider's: it picks the target, here one of the two pads.
const COLLISIONS = { pointerFirst, pointerWithin, rectIntersection, closestCenter, closestCorners };
const collision = ref<keyof typeof COLLISIONS>('pointerFirst');
</script>

<template>
  <DnDProvider :collision="COLLISIONS[collision]">
    <div class="demo">
      <code class="call">&lt;DnDProvider :collision="{{ collision }}"&gt;</code>
      <div class="collisions" role="radiogroup" aria-label="collision">
        <label v-for="name in Object.keys(COLLISIONS)" :key="name" :class="{ on: collision === name }">
          <input v-model="collision" type="radio" :value="name" />
          {{ name }}
        </label>
      </div>
      <ModifierLab />
    </div>
  </DnDProvider>
</template>

<style scoped>
.demo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.collisions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px;
  max-width: 100%;
  padding: 3px;
  border-radius: 9px;
  background: color-mix(in srgb, currentColor 7%, transparent);
}

.call {
  font: 11px/1.4 ui-monospace, Menlo, Consolas, monospace;
  color: #42b883;
}

label {
  padding: 4px 8px;
  border-radius: 6px;
  font: 11px/1.3 ui-monospace, Menlo, Consolas, monospace;
  cursor: pointer;
}

label.on {
  background: Canvas;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.25);
  font-weight: 600;
}

label:has(input:focus-visible) {
  outline: 2px solid #42b883;
}

input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
</style>

모디파이어

import { restrictToParent, snapToGrid } from '@vue-dnd-kit/core';

makeSortableList(list, { items, modifiers: [restrictToParent] });
makeDragArea(board, { modifiers: [snapToGrid({ x: 24, y: 24, smooth: true })] });

모디파이어는 드래그의 오프셋을 받아 새 오프셋을 반환합니다. 실행 순서는 프로바이더의 modifiers, 드래그 영역의 modifiers, draggable 자체(또는 그 리스트)의 modifiers, 그다음 영역의 경계(restrictToArea), 마지막으로 axis 고정입니다. 축, 경계, 그리드를 참고하세요.

Modifier

세로로만 움직입니다. 가로로는 페이지가 어떻게 스크롤되든 시작한 콘텐츠를 따라갑니다(containerShift). axis: 'y' 옵션도 같은 일을 하며, 마지막에 적용됩니다.

Modifier

가로로만 움직입니다. 세로로는 페이지가 어떻게 스크롤되든 시작한 콘텐츠를 따라갑니다(containerShift). axis: 'x' 옵션도 같은 일을 하며, 마지막에 적용됩니다.

Modifier

오버레이를 창 안에 가둡니다.

Modifier

오버레이를 드래그가 시작된 컨테이너 안에 가둡니다: 정렬 가능한 리스트(DOM상의 부모가 아님), 일반 draggable이면 부모 요소.

(target: MaybeElementRef) => Modifier

오버레이를 요소 안에 가둡니다: 요소, ref, 또는 getter.

Modifier

오버레이를 드래그 중인 요소의 첫 번째 스크롤 가능한 조상 안에 가둡니다.

(size: number | SnapToGridOptions) => Modifier

오버레이를 그리드의 가장 가까운 셀에 스냅합니다. 숫자는 정사각형 셀의 크기입니다. 옵션으로 축별 설정, 그리드가 시작하는 곳, 셀 사이를 부드럽게 미끄러지는 효과를 정합니다(SnapToGridOptions).

Modifier

잡은 위치의 오프셋을 유지하는 대신, 오버레이의 중심을 포인터 아래에 맞춥니다.

snapToGrid의 옵션.

x?
number

셀의 너비(px). 없으면(또는 0이면) 드래그가 x축으로 자유롭게 움직입니다.

y?
number

셀의 높이(px). 없으면(또는 0이면) 드래그가 y축으로 자유롭게 움직입니다. { y: 15 }는 캘린더 일정의 시간만 스냅합니다.

'container' | 'delta'

'container'(기본값): 오버레이의 왼쪽 위 모서리가 컨테이너의 왼쪽 위에서부터 그린 그리드 선에 안착합니다(containerRect: 정렬 가능한 리스트 또는 부모 요소). 'delta': 드래그 오프셋을 반올림하므로, 항목이 시작한 위치가 그리드에서 벗어나 있던 만큼 그대로 유지됩니다.

boolean | AnimationOptions

스냅된 위치 사이에서 오버레이를 부드럽게 움직입니다(기본값 80ms). 충돌 감지는 여전히 스냅된 위치를 바로 사용합니다.

드래그 중인 항목이 가는 곳을 바꿉니다. 드래그의 오프셋(transform)을 받아 새 오프셋을 반환합니다.

type Modifier = (args: ModifierArgs) => Coordinates

모디파이어가 드래그가 움직일 때마다 받는 것.

Coordinates

앞선 모디파이어가 수정한, 드래그 시작점 기준의 오프셋.

Active

현재 드래그.

Rect

드래그 시작 시점의 드래그 중인 요소의 사각형.

Rect

오버레이 박스를 현재 크기 그대로 transform만큼 옮겼을 때의 사각형. overlayFit: 'slot'이면 박스가 포인터를 중심으로 크기가 바뀌므로, 항상 activeRect를 transform만큼 옮긴 것과 같지는 않습니다.

Coordinates

드래그 시작 시점의 포인터 위치.

Rect | null

드래그 중인 항목의 정렬 가능한 리스트 컨테이너(또는 부모 요소)의 현재 위치입니다(스크롤을 따라갑니다).

Coordinates

드래그가 시작된 내용이 시작 이후 화면에서 얼마나 움직였는지. 컨테이너가 움직인 것(페이지나 그것을 감싼 컨테이너가 스크롤됨, 레이아웃이 밀림)과 그 안에서 내용이 스크롤된 것입니다. 축 고정은 다른 축을 이 값에 맞춰 두므로, 드래그는 그 내용에서 자기 행이나 열에 머뭅니다.

Rect

창(뷰포트)의 사각형.

Over | null

드래그 아래에 있는 드롭 대상(마지막으로 찾은 것). 아무것도 없으면 null.

충돌 감지

import { closestCorners } from '@vue-dnd-kit/core';
<DnDProvider :collision="closestCorners" />

프로바이더의 collision이 대상을 고릅니다. 가장 적합한 후보가 맨 앞에 옵니다.

CollisionDetection

기본값: 포인터 아래에 있는 것, 없으면 오버레이가 겹친 것.

CollisionDetection

포인터 아래에 있는 대상. 히트 테스트로 찾으며, z-order, 오버레이, shadow root를 고려합니다.

CollisionDetection

오버레이와 겹치는 대상: 우선순위가 높은 것, 그다음 더 깊이 중첩된 것, 그다음 IoU(intersection over union)가 큰 것.

CollisionDetection

모든 대상을 중심 사이의 거리로 정렬합니다.

CollisionDetection

모든 대상을 모서리 사이 거리의 합으로 정렬합니다(칸반 컬럼처럼 쌓인 대상에 적합합니다).

후보 id를 반환합니다. 가장 적합한 것이 맨 앞입니다.

type CollisionDetection = (args: CollisionArgs) => Key[]

충돌 감지가 드래그가 움직일 때마다 받는 것.

Coordinates

뷰포트 좌표의 포인터. 모디파이어를 적용한 뒤의 값입니다.

Rect | null

드래그 중인 박스(오버레이, 또는 overlay: false일 때는 요소 자체)를 드래그가 옮겨 놓은 위치에서 잰 사각형.

CollisionCandidate[]

드래그가 갈 수 있는 모든 드롭 대상. 그 accept 규칙이 드래그를 받는지와 상관없습니다.

Key[]

히트 테스트로 찾은 포인터 아래의 드롭 대상(z-order와 shadow root를 고려합니다). 가장 적합한 것이 맨 앞입니다.

충돌 감지가 고를 수 있는 드롭 대상: 활성화되어 있고, 페이지에 있으며, 완전히 잘리지 않은 대상.

Key

드롭 대상의 id.

Rect

대상의 보이는 부분: 스크롤 컨테이너와 뷰포트로 잘린 영역.

number

대상의 priority(기본값 0): 대상이 중첩 없이 겹칠 때 높은 쪽이 이깁니다. 정렬 가능한 항목은 컨테이너를 이깁니다.

number

드롭 대상 사이의 중첩 단계: 최상위는 0이고, 더 깊은 대상일수록 값이 큽니다.