스냅샷 기반 효과는 교체 가능한 SnapshotCapture 어댑터를 통해 픽셀을 받습니다. 코어 라이브러리는 특정 DOM-to-Canvas 엔진에 의존하지 않습니다. 루트 엔트리는 사용자 어댑터를 받고, /snapdom은 바로 사용할 수 있는 어댑터를 제공합니다.
SnapshotCapture
type SnapshotCapture = (
element: HTMLElement,
context: SnapshotCaptureContext,
) => HTMLCanvasElement | Promise<HTMLCanvasElement>;
interface SnapshotCaptureContext {
operation: 'remove' | 'restore' | 'prepare';
signal: AbortSignal;
invalidate?: boolean;
restoreRootOpacity?: string;
}
어댑터는 element의 현재 시각적 표현이 담긴 canvas를 반환해야 합니다. canvas의 픽셀 크기가 원본 해상도를 정합니다. 라이브러리는 요소의 CSS 경계를 별도로 측정하고 그 위에 애니메이션 오버레이를 배치합니다.
| 컨텍스트 필드 | 의미 |
|---|---|
operation | 백그라운드 캡처에서는 prepare, 그 외에는 현재 remove 또는 restore 작업 |
signal | 준비, 작업 또는 소유 인스턴스가 취소될 때 중단됨 |
invalidate | 명시적 준비 또는 캐시 무효화 후 캡처 엔진의 캐시 갱신을 요청합니다 |
restoreRootOpacity | restore()가 실제 요소를 일시적으로 감추기 전 루트의 계산된 opacity |
비용이 큰 작업 전에 signal.aborted를 확인하고, 기반 엔진이 취소를 지원하면 즉시 중단하세요. 복원 시에는 일시적으로 감춰진 상태가 캡처되지 않도록 캡처 루트에 restoreRootOpacity를 적용하세요.
import Disintegrator, { type SnapshotCapture } from 'vanilla-disintegrate';
const capture: SnapshotCapture = async (element, context) => {
if (context.signal.aborted) {
throw new DOMException('Capture aborted.', 'AbortError');
}
return captureWithMyEngine(element, {
signal: context.signal,
invalidate: context.invalidate,
rootOpacity: context.restoreRootOpacity,
});
};
const effects = new Disintegrator({
preset: 'dust',
capture,
});
DOM, SVG, CSS, WAAPI 또는 원본 픽셀이 필요 없는 다른 렌더러를 사용하는 사용자 효과 단계에는 needsSnapshot: false를 지정하세요. 두 단계 모두 스냅샷이 필요 없다면 /core 엔트리를 사용해 캡처와 파티클 의존성을 완전히 제외할 수 있습니다.
createSnapdomCapture(options?)
어댑터는 SnapDOM ^3.1.0과 SVG 렌더러를 사용합니다. SnapdomCaptureOptions는 canvas와 engine을 제외한 현재 SnapdomOptions를 받습니다. 각 캡처는 효과가 안전하게 해제할 수 있는 독립적인 canvas를 반환합니다.
명시적인 width 또는 height가 scale보다 우선하며, dpr은 출력 해상도를 곱합니다. 예를 들어 { width: 200, scale: 2, dpr: 2 }는 픽셀 예산 적용 전 너비 400픽셀의 canvas를 요청합니다.
maxCapturePixels의 기본값은 8,000,000입니다. 어댑터는 래스터화 전에 DPR을 낮춰 예산을 지킵니다. false는 제한을 해제합니다. 예산은 출력 비트맵에 적용되며 DOM 순회나 리소스 임베딩 비용을 제한하지 않습니다. 파티클의 renderQuality는 캡처 후 별도로 적용됩니다.
import Disintegrator, { createSnapdomCapture } from 'vanilla-disintegrate/snapdom';
const capture = createSnapdomCapture({
dpr: 2,
exclude: '[data-capture-ignore]',
});
const effects = new Disintegrator({ preset: 'dust', capture });
어댑터는 스냅샷에서 요소 크기와 텍스트 줄바꿈을 유지하도록 기본적으로 reconcile: true를 사용합니다. 레이아웃 측정 단계가 추가되며, reconcile: false로 건너뛸 수 있습니다. 나머지 설정은 embedFonts: 'auto', invalidate: false, filterMode: 'hide' 등 SnapDOM 기본값을 따릅니다. 자동 DPR의 상한은 2이며 명시적인 dpr은 이를 재정의합니다. 조건에 맞는 변경되지 않은 캡처는 SnapDOM의 자동 캐시를 사용합니다.
이미지는 SnapDOM이 처리합니다. placeholders: false는 실패한 이미지의 자리를 비워 두고, fallbackURL은 대체 이미지를 지정합니다. 사용자 filter는 그대로 전달됩니다. 리소스 대기로 캡처가 지연될 수 있으므로 사용자 정의 지연 로딩 이미지는 효과를 시작하기 전에 준비하세요.
기본 출력은 회전과 배율을 포함한 루트 요소의 사각형에 맞으며 그림자나 블러의 추가 여백을 포함하지 않습니다. 명시적인 clip, 활성화된 outerShadows, 또는 outerTransforms: false는 요청한 SnapDOM 캡처 영역을 사용합니다. Safari에서는 임베딩된 글꼴과 SVG의 선명도를 유지하도록 밀도를 보정합니다. 복원 캡처는 실제 요소를 숨긴 채 루트의 원래 불투명도를 유지합니다.
sheet.insertRule() 또는 CSSStyleRule.style 같은 CSSOM 변경 후에는 effects.invalidate(element)를 호출하세요. 준비된 스냅샷을 버리고 SnapDOM 스타일 갱신을 요청하며, snapdom.invalidate: false인 경우에도 적용됩니다. 명시적인 prepare()도 갱신을 요청하고 clearPrepared()는 다음 캡처에서 갱신하도록 합니다. capture를 단독 호출할 때는 해당 호출에 context.invalidate: true를 전달하거나, 매번 갱신하려면 invalidate: true를 설정하세요.
준비된 canvas는 별도의 수명 주기를 가집니다. 변경 관찰은 기본적으로 꺼져 있습니다. 시각적 변경 후 effects.invalidate()를 호출하거나 DOM 변경에 대해 preparation.observeMutations를 켜세요. CSSOM 변경은 여전히 명시적 무효화가 필요합니다. 플러그인은 SnapDOM 플러그인 계약을 따릅니다.
SnapDOM은 진행 중인 캡처를 취소할 수 없습니다. 어댑터는 시작 전에 취소된 호출을 거부하며, 작업 취소 후 도착한 결과는 라이브러리가 해제합니다.
/snapdom 생성자
import Disintegrator from 'vanilla-disintegrate/snapdom';
type SnapdomDisintegratorOptions = DisintegratorOptions & {
snapdom?: SnapdomCaptureOptions;
};
const effects = new Disintegrator({
preset: 'vapor',
snapdom: { dpr: 1.5 },
});
snapdom은 자동 생성된 어댑터에 옵션을 전달합니다. capture를 직접 제공하면 해당 어댑터를 완전히 대체하며, 이때 snapdom은 아무 효과가 없습니다.
루트 vanilla-disintegrate 엔트리는 SnapDOM을 가져오지 않으며, 선택한 효과 단계에 스냅샷이 필요할 때만 capture를 요구합니다.
캡처 해상도와 렌더링 품질
캡처와 렌더링은 별개의 단계입니다.
- 캡처 어댑터가 원본 canvas를 만들고 픽셀 밀도를 선택합니다.
- 파티클 렌더러가 원본을 WebGL 텍스처와 확장 애니메이션 표면으로 바꿀 때
renderQuality를 적용합니다.
renderQuality를 높여도 캡처 canvas에 없는 세부 정보를 복구할 수 없습니다. 캡처 DPR을 높이면 원본 픽셀이 늘어나므로 캡처 시간, 메모리 사용량, 텍스처 업로드 비용과 경우에 따라 파티클 준비 비용도 증가합니다.
어떤 DOM-to-Canvas 엔진도 브라우저가 그린 모든 픽셀을 그대로 재현한다고 보장할 수 없습니다. 텍스트 래스터화, 브라우저 확대, 필터, 임베디드 콘텐츠, 교차 출처 리소스의 알려진 차이는 제한 사항 문서를 참고하세요.