react-image-crop
react-image-crop copied to clipboard
Canvas toBlob crop not working on Sandbox (iOS)
I've been wrestling with the canvas logic for getting the cropped image on Mobile Safari and toBlob/toDataURL consistently return null.
I thought it might be something with my own product code, but it appears that the same issue happens on the code sandbox within the IOS Simulator. Very easy to reproduce on an iPhone 15 simulator using the Sandbox url.
Does anyone have a work around?
I've run into this same issue for mobile users on Safari with the preview canvas toBlob method failing to return a blob. It had been working well for months, but on January 10 we started receiving bug reports, all from users on mobile Safari browser and iOS version >17.0.
The behavior I've seen is like in @tylerjbainbridge's screenshot above, where the preview canvas does not populate with an image when the image is first selected. This seems to be happening more often with larger images.
Thanks for looking into this issue, we're also keen to know if anyone's found a work around or a source of the issue.
Are you able to replicate the issue? There was a "Canvas lost" error regression in iOS 17 that was fixed in a patch, wondering if you are able to see what error is in the console
I included replication instructions in the issue- very easy to reproduce it.
I believe it has to do with Safari/iOS having a max size for canvases and any larger image (basically anything taken on an iPhone) causes toBlob to quietly fail and return null.
I ended up having to move my image cropping to the server because this bug was effecting so many users.
Thanks for looking into this issue, we're also keen to know if anyone's found a work around or a source of the issue.
I just experienced a similar error now. I can create an issue for this if needed.
I found a fix for this 💯
The solution is shown in the image below:
-
when we try to draw canvas on iOS, for downloadable canvas, the pixel ratio
MUSTbe 1. if we use the default (the actual device pixelRatio which is 3 or more), the cropping is not going to work because the file will be too big to fit into a blob -
the one in green works on both iOS and android. However, the one in red work for every versions of Android but some versions iOS on mobile are not working.
The exact maximum size of a
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
I'm not sure if devicePixelRatio affects that you could just make a larger canvas and see.
So the formula is either:
const MAX_SIZE = 4096
or
const MAX_SIZE = 4096 / devicePixelRatio
Then just ensure the crop preview doesn't exceed that (size it down to the max dimensions if exceeded). canvas.drawImage has params which allow you to resize the image:
dWidth The width to draw the image in the destination canvas. This allows scaling of the drawn image. If not specified, the image is not scaled in width when drawn. Note that this argument is not included in the 3-argument syntax.
dHeight The height to draw the image in the destination canvas. This allows scaling of the drawn image. If not specified, the image is not scaled in height when drawn. Note that this argument is not included in the 3-argument syntax.
You can also dynamically determine the max canvas size with that library: https://npmjs.com/package/canvas-size