(rootEl: HTMLElement, options?: CaptureOptions)
| 198 | } |
| 199 | |
| 200 | export async function captureAndDownloadPng(rootEl: HTMLElement, options?: CaptureOptions): Promise<void> { |
| 201 | // 提高默认清晰度:maxExportWidth 2160(2K),minScale 1(不缩小) |
| 202 | const maxExportWidth = options?.maxExportWidth ?? 2160 |
| 203 | const minScale = options?.minScale ?? 1 |
| 204 | const fullContent = options?.fullContent !== false // 默认为 true |
| 205 | |
| 206 | // 获取元素的实际背景色(优先用户指定,否则自动检测) |
| 207 | const bgColor = options?.backgroundColor ?? getEffectiveBackground(rootEl) |
| 208 | |
| 209 | // 计算元素尺寸:如果需要完整内容,使用 scrollWidth/scrollHeight |
| 210 | const elementWidth = fullContent ? rootEl.scrollWidth : rootEl.getBoundingClientRect().width |
| 211 | let captureScale = Math.min(1, maxExportWidth / Math.max(1, elementWidth)) |
| 212 | captureScale = Math.max(minScale, captureScale) |
| 213 | |
| 214 | const snapOptions: Record<string, unknown> = { |
| 215 | scale: captureScale, |
| 216 | // 禁用字体嵌入可以避免某些 Unicode 字符导致的 encodeURIComponent 错误 |
| 217 | embedFonts: options?.embedFonts ?? false, |
| 218 | compress: options?.compress ?? true, |
| 219 | backgroundColor: bgColor, |
| 220 | crossOrigin: options?.crossOrigin ?? 'anonymous', |
| 221 | } |
| 222 | |
| 223 | const result = await ( |
| 224 | snapdom as ( |
| 225 | element: Element, |
| 226 | options: Record<string, unknown> |
| 227 | ) => Promise<{ |
| 228 | toCanvas: () => Promise<unknown> |
| 229 | toPng: (options?: Record<string, unknown>) => Promise<unknown> |
| 230 | toImg: () => Promise<HTMLImageElement> |
| 231 | }> |
| 232 | )(rootEl, snapOptions) |
| 233 | |
| 234 | // Preferred: Canvas path, apply background and scale again if needed, export PNG |
| 235 | try { |
| 236 | const canvas: unknown = await result.toCanvas() |
| 237 | if (canvas && (canvas as HTMLCanvasElement).toDataURL) { |
| 238 | const srcCanvas = canvas as HTMLCanvasElement |
| 239 | const outCanvas = document.createElement('canvas') |
| 240 | const scale2 = srcCanvas.width > maxExportWidth ? maxExportWidth / srcCanvas.width : 1 |
| 241 | outCanvas.width = Math.round(srcCanvas.width * scale2) |
| 242 | outCanvas.height = Math.round(srcCanvas.height * scale2) |
| 243 | const ctx = outCanvas.getContext('2d') |
| 244 | if (ctx) { |
| 245 | ctx.fillStyle = bgColor |
| 246 | ctx.fillRect(0, 0, outCanvas.width, outCanvas.height) |
| 247 | ctx.drawImage(srcCanvas, 0, 0, outCanvas.width, outCanvas.height) |
| 248 | const url = outCanvas.toDataURL('image/png') |
| 249 | const ts = new Date().toISOString().replace(/[:.]/g, '-') |
| 250 | triggerDownload(url, options?.filename ?? `wlb-report-${ts}.png`) |
| 251 | return |
| 252 | } |
| 253 | } |
| 254 | } catch { |
| 255 | // fallback below |
| 256 | } |
| 257 |
nothing calls this directly
no test coverage detected