-
-
Notifications
You must be signed in to change notification settings - Fork 343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Canvas toBlob crop not working on Sandbox (iOS) #574
Comments
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. |
I just experienced a similar error now. I can create an issue for this if needed. |
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size I'm not sure if So the formula is either: Then just ensure the crop preview doesn't exceed that (size it down to the max dimensions if exceeded).
You can also dynamically determine the max canvas size with that library: https://npmjs.com/package/canvas-size |
Hey All, just in case anyone else runs into this issue here is what I did, if you seen any flaws please respond to the comment 😅 . import canvasSize from 'canvas-size'
export const processFile = async (
crop: Crop,
previewCanvasRef: HTMLCanvasElement,
image: HTMLImageElement
) => {
const ctx = previewCanvasRef.getContext('2d')
if (!ctx || !crop) {
return
}
const area = await canvasSize.maxArea()
const constraints = area.success
? {
height: area.height,
width: area.width,
pixels: area.height * area.width,
}
: { height: 4096, width: 4096, pixels: 4096 * 4096 }
const pixelRatio = window.devicePixelRatio || 1
const scaleX = image.naturalWidth / image.width
const scaleY = image.naturalHeight / image.height
const cropWidth = crop.width * scaleX * pixelRatio
const cropHeight = crop.height * scaleY * pixelRatio
const cropAspectRatio = cropWidth / cropHeight
let resizedCropWidth = cropWidth
let resizedCropHeight = cropHeight
if (resizedCropWidth > constraints.width) {
resizedCropWidth = constraints.width
resizedCropHeight = resizedCropWidth / cropAspectRatio
}
if (resizedCropHeight > constraints.height) {
resizedCropHeight = constraints.height
resizedCropWidth = resizedCropHeight * cropAspectRatio
}
ctx.canvas.width = Math.floor(resizedCropWidth)
ctx.canvas.height = Math.floor(resizedCropHeight)
ctx.scale(pixelRatio, pixelRatio)
ctx.imageSmoothingQuality = 'high'
const cropX = crop.x * scaleX
const cropY = crop.y * scaleY
ctx.save()
ctx.drawImage(
image,
cropX,
cropY,
cropWidth,
cropHeight, // Source crop area in the image
0,
0,
resizedCropWidth,
resizedCropHeight // Destination on the canvas
)
ctx.restore()
} |
Just to note on the above example, there is an issue if your user is zoomed in or out, we need to consider this otherwise the crop will be off. This is on my list for next week so I'll update the above if I find a fix 🙇 |
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?
The text was updated successfully, but these errors were encountered: