Skip to content

Commit 8e96861

Browse files
committed
refactor: use PNG format for all small image exports
- Remove JPEG format, use PNG everywhere for consistency - Keep transparency (no white background) in small images - Both export and copy small image now use the same approach: scale down until <50KB while preserving transparency
1 parent 0369a29 commit 8e96861

1 file changed

Lines changed: 13 additions & 33 deletions

File tree

src/components/ChartContainer.jsx

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -118,65 +118,50 @@ export default function ChartContainer({
118118
link.click();
119119
}, []);
120120

121-
const exportChartSmallImage = useCallback((id) => {
121+
const exportChartSmallImage = useCallback(async (id) => {
122122
const chart = chartRefs.current.get(id);
123123
if (!chart) return;
124124

125125
const maxSize = 50 * 1024; // 50KB
126126
const canvas = chart.canvas;
127127

128-
// Create a temporary canvas for resizing
129128
const tempCanvas = document.createElement('canvas');
130129
const ctx = tempCanvas.getContext('2d');
131130

132-
// Start with original size and reduce if needed
133131
let scale = 1;
134-
let quality = 0.8;
135-
let dataUrl;
132+
let blob;
136133
let attempts = 0;
137-
const maxAttempts = 20;
134+
const maxAttempts = 10;
138135

139-
// Try to get image under 50KB by adjusting quality and scale
136+
// Use PNG format with scaling to reduce size while keeping transparency
140137
while (attempts < maxAttempts) {
141138
const width = Math.floor(canvas.width * scale);
142139
const height = Math.floor(canvas.height * scale);
143140

144141
tempCanvas.width = width;
145142
tempCanvas.height = height;
146-
147-
// Draw with white background (for JPEG)
148-
ctx.fillStyle = '#ffffff';
149-
ctx.fillRect(0, 0, width, height);
150143
ctx.drawImage(canvas, 0, 0, width, height);
151144

152-
dataUrl = tempCanvas.toDataURL('image/jpeg', quality);
153-
154-
// Calculate approximate file size (base64 is ~33% larger than binary)
155-
const base64Length = dataUrl.length - 'data:image/jpeg;base64,'.length;
156-
const fileSize = Math.ceil(base64Length * 0.75);
145+
blob = await new Promise(resolve => tempCanvas.toBlob(resolve, 'image/png'));
157146

158-
if (fileSize <= maxSize) {
147+
if (blob.size <= maxSize) {
159148
break;
160149
}
161150

162-
// Reduce quality first, then scale
163-
if (quality > 0.3) {
164-
quality -= 0.1;
165-
} else if (scale > 0.3) {
166-
scale -= 0.1;
167-
quality = 0.7; // Reset quality for new scale
168-
} else {
169-
// Can't reduce further, use what we have
151+
scale -= 0.1;
152+
if (scale < 0.2) {
170153
break;
171154
}
172155

173156
attempts++;
174157
}
175158

159+
const url = URL.createObjectURL(blob);
176160
const link = document.createElement('a');
177-
link.href = dataUrl;
178-
link.download = `${id}-small.jpg`;
161+
link.href = url;
162+
link.download = `${id}-small.png`;
179163
link.click();
164+
URL.revokeObjectURL(url);
180165
}, []);
181166

182167
const copyChartImage = useCallback(async (id) => {
@@ -209,26 +194,21 @@ export default function ChartContainer({
209194
let attempts = 0;
210195
const maxAttempts = 10;
211196

212-
// Clipboard API only supports PNG, so we reduce size by scaling down
197+
// Use PNG with scaling to reduce size while keeping transparency
213198
while (attempts < maxAttempts) {
214199
const width = Math.floor(canvas.width * scale);
215200
const height = Math.floor(canvas.height * scale);
216201

217202
tempCanvas.width = width;
218203
tempCanvas.height = height;
219-
220-
ctx.fillStyle = '#ffffff';
221-
ctx.fillRect(0, 0, width, height);
222204
ctx.drawImage(canvas, 0, 0, width, height);
223205

224-
// Convert to blob for size check
225206
blob = await new Promise(resolve => tempCanvas.toBlob(resolve, 'image/png'));
226207

227208
if (blob.size <= maxSize) {
228209
break;
229210
}
230211

231-
// Reduce scale to make image smaller
232212
scale -= 0.1;
233213
if (scale < 0.2) {
234214
break;

0 commit comments

Comments
 (0)