/** * ECharts Download Utilities * * Provides programmatic chart export functionality for downloading * charts as PNG or SVG images. These utilities wrap ECharts' built-in * export capabilities with a convenient API and sensible defaults. */ import type * as echarts from 'echarts'; // ─── Types ─────────────────────────────────────────────────────────────────── export type ExportFormat = 'png' | 'svg'; export interface DownloadOptions { /** The file name (without extension) */ fileName?: string; /** Export format: 'png' or 'svg' */ format?: ExportFormat; /** Pixel ratio for PNG exports (default: 2 for retina quality) */ pixelRatio?: number; /** Background color (default: '#ffffff' for PNG, 'none' for SVG) */ backgroundColor?: string; /** Components to exclude from the export (e.g. ['toolbox']) */ excludeComponents?: string[]; } // ─── Defaults ──────────────────────────────────────────────────────────────── const DEFAULT_FILE_NAME = 'open-meteo-chart'; const DEFAULT_PIXEL_RATIO = 2; // ─── Download Functions ────────────────────────────────────────────────────── /** * Downloads a single ECharts instance as an image file. * * @param chart - The ECharts instance to export * @param options - Download configuration options */ export function downloadChart(chart: echarts.ECharts, options: DownloadOptions = {}): void { const { fileName = DEFAULT_FILE_NAME, format = 'png', pixelRatio = DEFAULT_PIXEL_RATIO, backgroundColor, excludeComponents = ['toolbox'] } = options; const resolvedBg = backgroundColor ?? (format === 'svg' ? 'none' : '#ffffff'); // Use ECharts' getDataURL for PNG, getConnectedDataURL for SVG const dataUrl = chart.getDataURL({ type: format === 'svg' ? 'svg' : 'png', pixelRatio: format === 'png' ? pixelRatio : 1, backgroundColor: resolvedBg, excludeComponents }); triggerDownload(dataUrl, `${fileName}.${format}`); } /** * Downloads all provided ECharts instances as separate image files. * Each file is named with an incrementing suffix (e.g. chart-1.png, chart-2.png). * * @param charts - Array of ECharts instances to export * @param options - Download configuration options (fileName is used as prefix) */ export function downloadAllCharts( charts: echarts.ECharts[], options: DownloadOptions = {} ): void { const { fileName = DEFAULT_FILE_NAME, ...rest } = options; charts.forEach((chart, index) => { if (chart && !chart.isDisposed()) { downloadChart(chart, { ...rest, fileName: charts.length === 1 ? fileName : `${fileName}-${index + 1}` }); } }); } /** * Returns the data URL of a chart without triggering a download. * Useful for previewing or embedding chart images programmatically. * * @param chart - The ECharts instance to export * @param options - Export configuration options * @returns A base64-encoded data URL string */ export function getChartDataUrl( chart: echarts.ECharts, options: DownloadOptions = {} ): string { const { format = 'png', pixelRatio = DEFAULT_PIXEL_RATIO, backgroundColor, excludeComponents = ['toolbox'] } = options; const resolvedBg = backgroundColor ?? (format === 'svg' ? 'none' : '#ffffff'); return chart.getDataURL({ type: format === 'svg' ? 'svg' : 'png', pixelRatio: format === 'png' ? pixelRatio : 1, backgroundColor: resolvedBg, excludeComponents }); } // ─── Internal Helpers ──────────────────────────────────────────────────────── /** * Triggers a browser file download from a data URL. * Creates a temporary anchor element, clicks it, and removes it. */ function triggerDownload(dataUrl: string, fileName: string): void { const link = document.createElement('a'); link.href = dataUrl; link.download = fileName; link.style.display = 'none'; document.body.appendChild(link); link.click(); // Clean up the DOM after a brief delay to ensure the download starts requestAnimationFrame(() => { document.body.removeChild(link); }); }