Vanilla Disintegratev1.6.1
ZH
本页内容

基于快照的效果通过可替换的 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显式准备或缓存失效后,要求捕获引擎刷新自己的缓存
restoreRootOpacityrestore() 临时隐藏真实元素之前,根元素的原始计算 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 接受当前的 SnapdomOptions,但不包括 canvas 和 engine:每次捕获返回独立拥有的 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 可跳过该步骤。其他设置遵循 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 有独立生命周期。默认不观察 DOM 变更:视觉变化后调用 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 不产生作用。

根入口 vanilla-disintegrate 不会导入 SnapDOM,并且只有所选效果阶段需要快照时才要求提供 capture。

捕获分辨率与渲染质量

捕获和渲染是两个独立阶段:

  1. 捕获适配器创建源 canvas 并选择其像素密度。
  2. 粒子渲染器在把源内容转换为 WebGL 纹理和扩展动画表面时应用 renderQuality。

提高 renderQuality 无法恢复源 canvas 中不存在的细节。提高捕获 DPR 会产生更多源像素,因此会增加捕获时间、内存占用、纹理上传开销,并可能增加粒子准备成本。

任何 DOM-to-Canvas 引擎都不能保证逐像素复现浏览器的原始渲染。文本栅格化、浏览器缩放、滤镜、嵌入内容和跨域资源的已知差异请参阅限制章节。

在 GitHub 上编辑此页