Эффекты на основе снимка получают пиксели через заменяемый адаптер SnapshotCapture. Ядро библиотеки не зависит от конкретного DOM-to-Canvas-движка: корневой entry point принимает пользовательский адаптер, а /snapdom предоставляет готовый.
SnapshotCapture
type SnapshotCapture = (
element: HTMLElement,
context: SnapshotCaptureContext,
) => HTMLCanvasElement | Promise<HTMLCanvasElement>;
interface SnapshotCaptureContext {
operation: 'remove' | 'restore' | 'prepare';
signal: AbortSignal;
invalidate?: boolean;
restoreRootOpacity?: string;
}
Адаптер должен вернуть canvas с текущим визуальным представлением element. Размеры canvas в пикселях задают исходное разрешение; библиотека независимо измеряет CSS-границы элемента и размещает поверх них слой анимации.
| Поле контекста | Значение |
|---|---|
operation | prepare для фонового захвата либо активная операция remove или restore |
signal | Прерывается при отмене подготовки, операции или владеющего экземпляра |
invalidate | Запрашивает обновление кешей движка после явной подготовки или инвалидации |
restoreRootOpacity | Исходная вычисленная прозрачность корня до того, как restore() временно скрыл живой элемент |
Проверяйте 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,
});
Установите needsSnapshot: false для фазы пользовательского эффекта, которая анимирует DOM, SVG, CSS, WAAPI или другой рендерер без исходных пикселей. Если снимок не нужен обеим фазам, entry point /core полностью исключает зависимости захвата и частиц.
createSnapdomCapture(options?)
Адаптер использует SnapDOM ^3.1.0 и его SVG-рендерер. SnapdomCaptureOptions принимает актуальные SnapdomOptions, кроме canvas и engine: каждый захват возвращает собственный canvas, который эффект может безопасно освободить.
Явные width или height имеют приоритет над scale; dpr умножает разрешение результата. Например, { width: 200, scale: 2, dpr: 2 } запрашивает canvas шириной 400 пикселей до применения бюджета.
maxCapturePixels по умолчанию равен 8 000 000. Адаптер уменьшает DPR до растеризации, чтобы уложиться в бюджет; false отключает ограничение. Бюджет относится к итоговому bitmap, а не к обходу 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 отключает его. Остальные настройки следуют значениям SnapDOM по умолчанию, включая embedFonts: 'auto', invalidate: false и filterMode: 'hide'. Автоматический DPR ограничен значением 2; явный dpr переопределяет этот предел. Подходящие неизменившиеся снимки переиспользуются штатным кешем SnapDOM.
Изображения обрабатывает SnapDOM. placeholders: false сохраняет пустое место сломанной картинки; fallbackURL задаёт замену. Пользовательский filter передаётся без изменений. Ожидание ресурсов может задержать захват; нестандартную ленивую загрузку подготовьте до запуска эффекта.
По умолчанию итоговый снимок соответствует прямоугольнику корня с учётом поворота и масштаба, без дополнительного отступа для теней и размытия. Явный clip, включённый outerShadows или outerTransforms: false выбирают запрошенную геометрию SnapDOM. Для Safari применяется коррекция плотности, сохраняющая резкость встроенных шрифтов и SVG. При восстановлении снимок сохраняет исходную прозрачность корня, пока живой элемент скрыт.
После изменений CSSOM, например sheet.insertRule() или CSSStyleRule.style, вызывайте effects.invalidate(element). Метод удаляет подготовленные снимки и запрашивает обновление стилей SnapDOM, даже при snapdom.invalidate: false. Явный prepare() также запрашивает обновление; после clearPrepared() оно выполняется при следующих захватах. При самостоятельном вызове capture передайте context.invalidate: true для конкретного снимка либо настройте invalidate: true для обновления при каждом вызове.
У подготовленных canvas отдельный жизненный цикл. Наблюдение за мутациями по умолчанию выключено: после визуальных изменений вызывайте effects.invalidate() либо включайте preparation.observeMutations для изменений DOM. Изменения 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 ни на что не влияет.
Корневой entry point vanilla-disintegrate не импортирует SnapDOM и требует capture, только когда выбранной фазе эффекта нужен снимок.
Разрешение захвата и качество рендера
Захват и рендеринг — два отдельных этапа:
- Адаптер захвата создаёт исходный canvas и выбирает его плотность пикселей.
- Рендерер частиц применяет
renderQualityпри создании WebGL-текстур и расширенной поверхности анимации.
Повышение renderQuality не восстановит детали, которых нет в захваченном canvas. Повышение DPR захвата создаёт больше исходных пикселей, поэтому увеличивает время захвата, расход памяти, стоимость загрузки текстуры и потенциально стоимость подготовки частиц.
Ни один DOM-to-Canvas-движок не гарантирует воспроизведение каждого отрисованного браузером пикселя. Известные различия при растеризации текста, масштабе браузера, фильтрах, встроенном содержимом и cross-origin-ресурсах перечислены в разделе ограничений.