fix(canvas): 图片裁剪 - 修复云端图片跨域导致的确认裁剪无反应
裁剪属于像素级操作,需要先把图片画到 canvas 再导出。云端图片地址通常不带 CORS 头,canvas 会被标记为跨域,toDataURL 直接抛 SecurityError;而 loadImage 只挂了 onload、没有 onerror,加载失败时 Promise 永久挂起。两者叠加后,用户 侧的表现都是「点击确认裁剪没有任何反应」,控制台之外看不到原因。 - loadImage 补充 onerror,避免加载失败时 Promise 永不落地 - 仅对非 data:/blob: 的地址设置 crossOrigin=anonymous,本地资源设了反而 可能取不到像素 - 新增 resolveCroppableImageSource():优先用本地媒体缓存 Blob 构造同源 objectURL,取不到再回退原始地址,并在 finally 中 revoke - cropImageNode 补充 try/catch 与失败提示,让错误可见而不是静默失败 无外部行为变化,仅修复失败路径与错误反馈。
This commit is contained in:
@@ -159,9 +159,24 @@ function drawResizeCanvas(source: CanvasImageSource, sourceWidth: number, source
|
||||
}
|
||||
|
||||
function loadImage(dataUrl: string) {
|
||||
return new Promise<HTMLImageElement>((resolve) => {
|
||||
return new Promise<HTMLImageElement>((resolve, reject) => {
|
||||
const image = new Image();
|
||||
// 只有跨源 HTTP(S) 地址才需要声明匿名跨域;同源的 /api 资源不能
|
||||
// 强制走 CORS,否则缺少 ACAO 响应头时反而会加载失败。
|
||||
if (isCrossOriginHttpUrl(dataUrl)) image.crossOrigin = "anonymous";
|
||||
image.onload = () => resolve(image);
|
||||
// 缺少 onerror 时加载失败会让 Promise 永久挂起,调用方 await 后表现为「点击无反应」。
|
||||
image.onerror = () => reject(new Error("图片加载失败,无法处理该图片"));
|
||||
image.src = dataUrl;
|
||||
});
|
||||
}
|
||||
|
||||
function isCrossOriginHttpUrl(value: string) {
|
||||
if (typeof window === "undefined") return false;
|
||||
try {
|
||||
const url = new URL(value, window.location.href);
|
||||
return (url.protocol === "http:" || url.protocol === "https:") && url.origin !== window.location.origin;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user