返回 presentation-ai
infographic-preview-renderer.ts
根目录 / src / hooks / presentation / infographic / infographic-preview-renderer.ts
1 "use client";
2
3 import { Infographic, type InfographicOptions } from "@antv/infographic";
4
5 import { enforceInfographicCardBackground } from "@/components/notebook/presentation/editor/utils/infographic-card-background";
6 import { registerLucideIconLoader } from "./infographic-icon-loader";
7
8 type PreviewRenderer = {
9 container: HTMLDivElement;
10 infographic: Infographic;
11 };
12
13 let previewRenderer: PreviewRenderer | null = null;
14 let previewRenderQueue: Promise<void> = Promise.resolve();
15
16 function waitForAnimationFrame(): Promise<void> {
17 return new Promise((resolve) => {
18 window.requestAnimationFrame(() => resolve());
19 });
20 }
21
22 function getPreviewRenderer(): PreviewRenderer {
23 if (previewRenderer) return previewRenderer;
24
25 registerLucideIconLoader();
26
27 const container = document.createElement("div");
28 container.style.position = "fixed";
29 container.style.left = "-10000px";
30 container.style.top = "0";
31 container.style.width = "240px";
32 container.style.height = "135px";
33 container.style.pointerEvents = "none";
34 container.style.opacity = "0";
35 container.style.contain = "layout style paint";
36 document.body.appendChild(container);
37
38 previewRenderer = {
39 container,
40 infographic: new Infographic({
41 container,
42 width: "100%",
43 height: "100%",
44 editable: false,
45 }),
46 };
47
48 return previewRenderer;
49 }
50
51 async function renderInfographicPreviewHtmlTask(
52 payload: Partial<InfographicOptions> | string,
53 ): Promise<string> {
54 const { container, infographic } = getPreviewRenderer();
55
56 container.replaceChildren();
57 infographic.render(payload);
58 await waitForAnimationFrame();
59 await waitForAnimationFrame();
60 enforceInfographicCardBackground(container);
61
62 return container.innerHTML;
63 }
64
65 export function renderInfographicPreviewHtml(
66 payload: Partial<InfographicOptions> | string,
67 ): Promise<string> {
68 const task = previewRenderQueue.then(() =>
69 renderInfographicPreviewHtmlTask(payload),
70 );
71
72 previewRenderQueue = task.then(
73 () => undefined,
74 () => undefined,
75 );
76
77 return task;
78 }
79
79 lines TYPESCRIPT