12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
- import { snapdom } from '@zumer/snapdom';
- export interface SnapshotOption {
- immediate?: boolean;
- }
- type SnapshotTspl = (total?: number) => string;
- type SnapshotTemplate = (base64: string) => SnapshotTspl;
- export function useSnapshot<P extends Record<string, any>>(loader: () => Promise<{ default: Component }>, props?: P, option?: SnapshotOption) {
- const snapshot = shallowRef<string>();
- const tspl = shallowRef<SnapshotTspl | void>();
- let app: ReturnType<typeof createApp> | null = null;
- let container: HTMLDivElement | null = null;
- const mounted = (component: Component, _props?: Partial<P>) => {
- if (container == null) return;
- const { promise, resolve } = Promise.withResolvers<SnapshotTemplate>();
- app = createApp(component, { ...props, ..._props, onRendered: resolve });
- app.mount(container);
- return promise;
- };
- const unmounted = () => {
- app?.unmount();
- app = null;
- };
- const capture = async (template?: SnapshotTemplate) => {
- if (container == null) return;
- const dom = await snapdom(container, { scale: 1 });
- const img = await dom.toPng({ scale: 2 });
- snapshot.value = img.src;
- tspl.value = template?.(img.src);
- };
- async function render(props?: Partial<P>, forced = false): Promise<{ snapshot: string; tspl: SnapshotTspl }> {
- if (forced) unmounted();
- if (forced || !snapshot.value) {
- const { default: component } = await loader();
- const tspl = await mounted(component, props);
- await capture(tspl);
- unmounted();
- }
- return {
- snapshot: snapshot.value!!,
- tspl: tspl.value!!,
- };
- }
- tryOnMounted(() => {
- container = document.createElement('div');
- container.style.position = 'fixed';
- container.style.left = '-99999px';
- container.style.top = '-99999px';
- container.style.zIndex = '-1';
- document.body.appendChild(container);
- if (option?.immediate) render().then();
- });
- tryOnUnmounted(() => {
- if (container) document.body.removeChild(container);
- container = null;
- unmounted();
- snapshot.value = '';
- tspl.value = void 0;
- });
- return { snapshot, tspl, render };
- }
|