修改已加载HTMLImageElement的src是否触发load事件?图片缩放代码求助
load Event Questions Hey there! Let's tackle your two key questions and the issue you're hitting with your image scaling feature.
Does modifying an HTMLImageElement's src trigger the load event again?
Short answer: Yes, but only if the new src value is different from the current one.
Here's the breakdown:
- If you set
image.srcto a new, unique URL (even if the resource is cached), the browser will initiate a load (or pull from cache) and fire theloadevent once the resource is ready. - If you set
image.srcto the exact same URL it already has, the browser won't re-initiate a load—so noloadevent fires. This is probably what you're seeing when your image is already loaded.
Why isn't the load event firing when you modify src post-load?
Based on your scenario, the most likely culprit is that you're either:
- Reusing the same
srcvalue for the image (so the browser skips reloading), or - Trying to listen for the
loadevent after it's already fired (if the cached resource loads instantly, your Observable might miss it).
But here's a better approach for your image scaling goal: you don't need to re-set the src to scale the image. Once the original image loads, you can handle all scaling directly in a canvas, avoiding the load event entirely for subsequent resizes.
Optimized Code for Your 25% Iterative Scaling
Instead of relying on reloading the image, use canvas to iteratively shrink the image until it meets your size requirements:
generateData(data: File) { const image = new Image(); image.src = URL.createObjectURL(data); return Observable.fromEvent(image, 'load').pipe( map(() => { let currentWidth = image.width; let currentHeight = image.height; const targetWidth = /* Define your target width here */; const targetHeight = /* Define your target height here */; // Initialize canvas with original image dimensions let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); canvas.width = currentWidth; canvas.height = currentHeight; ctx.drawImage(image, 0, 0); // Iteratively shrink by 25% until we hit the target size while (currentWidth > targetWidth || currentHeight > targetHeight) { // Calculate new dimensions (75% of current) currentWidth *= 0.75; currentHeight *= 0.75; // Create a temporary canvas for the scaled version const tempCanvas = document.createElement('canvas'); tempCanvas.width = currentWidth; tempCanvas.height = currentHeight; const tempCtx = tempCanvas.getContext('2d'); // Draw the current canvas onto the temp canvas at the new size tempCtx.drawImage(canvas, 0, 0, currentWidth, currentHeight); // Replace the main canvas with the scaled temp canvas canvas = tempCanvas; } // Clean up the object URL to free memory URL.revokeObjectURL(image.src); // Return the final scaled image (adjust format/quality as needed) return canvas.toDataURL('image/jpeg', 0.9); }) ); }
Key Notes
- This approach avoids the
loadevent issue entirely because we only load the original image once. - Don't forget to call
URL.revokeObjectURL(image.src)after loading to free up browser memory. - If you do need to reload an image with a new
src, always ensure the URL is unique (even adding a cache-busting query param like?v=1if needed) and attach yourloadlistener before setting thesrc.
内容的提问来源于stack exchange,提问作者bakaou baka

