@@ -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