Export Options
Relevant source files
The following files were used as context for generating this wiki page:The Export Options feature provides the user with the ability to download the generated QR code in various image formats. The system supports both raster (PNG, JPG) and vector (SVG) formats, with additional options for background color, transparency, and padding to ensure scannability.
The primary user interface for this feature is the ExportPanel component, which orchestrates the export process by gathering user settings and invoking utility functions from qr-helpers.js to generate and trigger the download of the final image file. The entire process is handled on the client-side without any server interaction.
Sources: src/components/ExportPanel.jsx, README.md:27-30
Architecture and Data Flow
The export functionality is initiated by the user from the ExportPanel component. This component receives the necessary data and references (e.g., canvasRef, svgRef, color settings) from the main App component. Based on the selected format, it calls the appropriate helper function to construct the image data, which is then passed to a download utility.
Download Process Flow
The following diagram illustrates the sequence of events when a user initiates a download.
This diagram shows the user interaction leading to the handleDownload function call, which then coordinates with browser APIs and helper functions to generate and save the file.
Sources: src/components/ExportPanel.jsx:21-91
Core Components
The export functionality is primarily managed by the ExportPanel component and a set of utility functions in qr-helpers.js.
ExportPanel.jsx
This React component renders the download buttons (PNG, JPG, SVG) and contains the primary logic for handling the export process.
Key Properties:
| Prop | Type | Description | Source |
|---|---|---|---|
format | string | The current QR code format ('canvas' or 'svg'). | src/components/ExportPanel.jsx:7 |
canvasRef | React.RefObject | A reference to the wrapper of the <canvas> element. | src/components/ExportPanel.jsx:8 |
svgRef | React.RefObject | A reference to the wrapper of the <svg> element. | src/components/ExportPanel.jsx:9 |
includeMargin | boolean | Whether the user has enabled the "Quiet Zone". | src/components/ExportPanel.jsx:10 |
transparentBg | boolean | Whether the background should be transparent (for PNG). | src/components/ExportPanel.jsx:11 |
bgColor | string | The hex code for the background color. | src/components/ExportPanel.jsx:12 |
onError | Function | A callback to display toast notifications for errors or success. | src/components/ExportPanel.jsx:13 |
handleDownload(ext) function:
This is the central function triggered by the download buttons. It determines the source element (canvas or SVG), calculates necessary padding, handles format-specific logic (like JPG transparency), and calls the appropriate builder function.
Sources: src/components/ExportPanel.jsx:21-91
qr-helpers.js
This utility file contains the functions responsible for building the image data and triggering the download.
buildDataURL(canvas, ext, options)
This function generates a base64 data URL for raster formats (PNG/JPG). It can add padding and a background color to the source canvas. If rounded corners are specified, it clips the canvas to a rounded rectangle path.
// src/utils/qr-helpers.js:175-208
export function buildDataURL(canvas, ext, { padPx = 0, bg = '#FFFFFF', rounded = 0 } = {}) {
if (padPx === 0 && rounded === 0) {
return ext === 'jpg' ? canvas.toDataURL('image/jpeg', 1.0) : canvas.toDataURL('image/png', 1.0);
}
const w = canvas.width + padPx * 2;
const h = canvas.height + padPx * 2;
const temp = document.createElement('canvas');
// ... canvas creation and drawing logic ...
ctx.drawImage(canvas, padPx, padPx);
return ext === 'jpg' ? temp.toDataURL('image/jpeg', 1.0) : temp.toDataURL('image/png', 1.0);
}
buildSVGBlob(svgElement, options)
This function generates a Blob for SVG exports. It handles padding by creating a new, larger SVG, inserting a background <rect> element, and wrapping the original SVG content in a transformed <g> element to center it.
// src/utils/qr-helpers.js:217-248
export function buildSVGBlob(svgElement, { padPx = 0, bg = '#FFFFFF' } = {}) {
if (padPx === 0) {
const svgData = new XMLSerializer().serializeToString(svgElement);
return new Blob([svgData], { type: 'image/svg+xml' });
}
// Clone and add padding
const clone = svgElement.cloneNode(true);
// ... logic to add <rect> for background and <g> for transform ...
const svgData = new XMLSerializer().serializeToString(clone);
return new Blob([svgData], { type: 'image/svg+xml' });
}
downloadFile(data, filename)
A simple utility that creates a temporary <a> element to trigger the browser's file download dialog. It accepts either a data URL string or a Blob.
Sources: src/utils/qr-helpers.js:255-266
Export Formats
The application supports three primary export formats, each suited for different use cases. The format is determined by which download button the user clicks in the ExportPanel.
| Format | Implementation | Characteristics | Notes |
|---|---|---|---|
| PNG | Canvas (buildDataURL) | Raster format. Supports transparent backgrounds. Ideal for web and application use. | The transparentBg prop controls transparency. If false, the bgColor is used. |
| JPG | Canvas (buildDataURL) | Raster format. Does not support transparency. Generally smaller file size. | If transparentBg is true, a warning is shown, and the background defaults to white. |
| SVG | SVG (buildSVGBlob) | Vector format. Infinitely scalable without quality loss. Best for printing and high-resolution displays. | The format state in App.jsx is switched to 'svg' to render the QR code as an SVG element. |
Sources: src/components/ExportPanel.jsx:116-155, README.md:27-30, src/App.jsx:400-417
Special Handling
Quiet Zone (Margin)
The "Quiet Zone" is a mandatory blank area around a QR code. The application allows users to toggle this via the includeMargin prop. However, to prevent users from exporting non-scannable codes, the handleDownload function implements a safeguard:
- If
includeMarginisfalse, it calculates asafePaddingof 8% of the QR code's size. - It displays a
window.confirm()dialog to inform the user that this padding will be added automatically. - If the user confirms, the
padPxvalue is passed tobuildDataURLorbuildSVGBlob.
This logic ensures that even user-customized QR codes adhere to a minimum level of scannability.
Sources: src/components/ExportPanel.jsx:38-51, src/App.jsx:898-908
Error Handling
The export process includes specific error handling, primarily for issues related to cross-origin images used as logos.
- CORS Error: If a logo is loaded from a URL that doesn't support CORS, the canvas becomes "tainted." Attempting to export it via
toDataURLwill throw a security error. ThehandleDownloadfunction catches this error and displays a user-friendly message explaining the issue.
// src/components/ExportPanel.jsx:81-86
if (error.message?.includes('tainted') || error.message?.includes('cross-origin')) {
onError?.(
'❌ Lỗi CORS: Logo từ nguồn khác không cho phép export. Vui lòng upload logo từ máy hoặc dùng URL hỗ trợ CORS.',
'error',
);
}
- JPG Transparency: The code explicitly checks if the user is trying to export a JPG with a transparent background. Since JPG does not support transparency, it shows a warning and automatically uses the specified background color or defaults to white.
Sources: src/components/ExportPanel.jsx:59-65, src/components/ExportPanel.jsx:81-88