Keep cover crop image visible while zooming.

Do not revoke the preview blob URL until the dialog closes, so resizing the image on zoom does not blank it.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Michelle Zan
2026-10-08 13:19:15 +08:00
co-authored by Cursor
parent 0edd9fedf2
commit b4e1a041de
+21 -9
View File
@@ -158,6 +158,7 @@
const cropState = {
targetInput: null,
hint: null,
objectUrl: '',
naturalW: 0,
naturalH: 0,
scale: 1,
@@ -207,6 +208,13 @@
const w = cropState.naturalW * cropState.scale
const h = cropState.naturalH * cropState.scale
// Cover the crop window so zoom/pan never leaves it empty.
const minX = size.maskLeft + size.maskW - w
const maxX = size.maskLeft
const minY = size.maskTop + size.maskH - h
const maxY = size.maskTop
cropState.x = Math.min(maxX, Math.max(minX, cropState.x))
cropState.y = Math.min(maxY, Math.max(minY, cropState.y))
img.style.width = `${w}px`
img.style.height = `${h}px`
img.style.left = `${cropState.x}px`
@@ -250,31 +258,35 @@
function openCoverCrop(file, targetInput, hint) {
const modal = document.getElementById('cropModal')
const img = document.getElementById('cropImage')
if (cropState.objectUrl) URL.revokeObjectURL(cropState.objectUrl)
cropState.targetInput = targetInput
cropState.hint = hint
cropState.scale = 0
cropState.scale = 1
cropState.x = 0
cropState.y = 0
const url = URL.createObjectURL(file)
// Keep the blob URL alive until the dialog closes. Revoking it on load
// makes the image vanish the next time width/height change (zoom).
cropState.objectUrl = URL.createObjectURL(file)
img.onload = () => {
cropState.naturalW = img.naturalWidth
cropState.naturalH = img.naturalHeight
URL.revokeObjectURL(url)
modal.classList.add('on')
requestAnimationFrame(() => {
if (!fitCropImage()) {
setTimeout(() => fitCropImage(), 50)
}
if (!fitCropImage()) setTimeout(() => fitCropImage(), 50)
})
}
img.src = url
img.src = cropState.objectUrl
}
function closeCoverCrop() {
document.getElementById('cropModal').classList.remove('on')
document.getElementById('cropImage').removeAttribute('src')
const img = document.getElementById('cropImage')
img.removeAttribute('src')
if (cropState.objectUrl) {
URL.revokeObjectURL(cropState.objectUrl)
cropState.objectUrl = ''
}
cropState.targetInput = null
cropState.scale = 0
}
function exportCroppedFile() {