新增 现在参考图可以拖动排序了;

修复 双参考图生成结果显示问题;
This commit is contained in:
2025-09-22 22:39:45 +08:00
parent 690a530031
commit 260a7e4f0f
6 changed files with 430 additions and 192 deletions

View File

@@ -8,7 +8,9 @@ export const ImageCanvas: React.FC = () => {
const {
canvasImage,
canvasZoom,
canvasPan,
setCanvasZoom,
setCanvasPan,
brushStrokes,
addBrushStroke,
showMasks,
@@ -48,132 +50,194 @@ export const ImageCanvas: React.FC = () => {
// 加载图像
useEffect(() => {
let img: HTMLImageElement | null = null;
console.log('useEffect triggered, canvasImage:', canvasImage);
if (canvasImage) {
console.log('开始加载图像URL:', canvasImage);
// 如果没有图像URL直接返回
if (!canvasImage) {
console.log('没有图像需要加载');
setImage(null);
return;
}
let img: HTMLImageElement | null = null;
let isCancelled = false;
console.log('开始加载图像URL:', canvasImage);
img = new window.Image();
img.onload = () => {
// 检查是否已取消
if (isCancelled) {
console.log('图像加载被取消');
return;
}
img = new window.Image();
const isCancelled = false;
console.log('图像加载成功,尺寸:', img.width, 'x', img.height);
setImage(img);
img.onload = () => {
// 检查是否已取消
if (isCancelled) {
console.log('图像加载被取消');
return;
}
// 只在图像首次加载时自动适应画布
if (!isCancelled && img) {
const isMobile = window.innerWidth < 768;
const padding = isMobile ? 0.9 : 0.8;
console.log('图像加载成功,尺寸:', img.width, 'x', img.height);
setImage(img);
const scaleX = (stageSize.width * padding) / img.width;
const scaleY = (stageSize.height * padding) / img.height;
// 只在图像首次加载时自动适应画布
if (!isCancelled && img) {
const isMobile = window.innerWidth < 768;
const padding = isMobile ? 0.9 : 0.8;
const maxZoom = isMobile ? 0.3 : 0.8;
const optimalZoom = Math.min(scaleX, scaleY, maxZoom);
// 立即更新React状态以确保Konva Image组件使用正确的缩放值
setCanvasZoom(optimalZoom);
setCanvasPan({ x: 0, y: 0 });
// 使用setTimeout确保DOM已更新后再设置Stage
setTimeout(() => {
// 检查是否已取消
if (isCancelled) {
return;
}
const scaleX = (stageSize.width * padding) / img.width;
const scaleY = (stageSize.height * padding) / img.height;
const maxZoom = isMobile ? 0.3 : 0.8;
const optimalZoom = Math.min(scaleX, scaleY, maxZoom);
// 立即更新React状态以确保Konva Image组件使用正确的缩放值
setCanvasZoom(optimalZoom);
setCanvasPan({ x: 0, y: 0 });
// 使用setTimeout确保DOM已更新后再设置Stage
setTimeout(() => {
if (!isCancelled && img) {
// 直接设置缩放但保持Stage居中
const stage = stageRef.current;
if (stage) {
stage.scale({ x: optimalZoom, y: optimalZoom });
// 重置Stage位置以确保居中
stage.position({ x: 0, y: 0 });
stage.batchDraw();
if (!isCancelled && img) {
// 直接设置缩放但保持Stage居中
const stage = stageRef.current;
if (stage) {
stage.scale({ x: optimalZoom, y: optimalZoom });
// 重置Stage位置以确保居中
stage.position({ x: 0, y: 0 });
stage.batchDraw();
}
console.log('图像自动适应画布完成,缩放:', optimalZoom);
}
}, 0);
}
};
img.onerror = (error) => {
// 检查是否已取消
if (isCancelled) {
return;
}
console.error('图像加载失败:', error);
console.error('图像URL:', canvasImage);
// 检查是否是IndexedDB URL
if (canvasImage.startsWith('indexeddb://')) {
console.log('正在处理IndexedDB图像...');
// 从IndexedDB获取图像并创建Blob URL
const imageId = canvasImage.replace('indexeddb://', '');
import('../services/referenceImageService').then((module) => {
const referenceImageService = module;
referenceImageService.getReferenceImage(imageId)
.then(blob => {
// 检查是否已取消
if (isCancelled) {
return;
}
console.log('图像自动适应画布完成,缩放:', optimalZoom);
}
}, 0);
}
};
img.onerror = (error) => {
if (!isCancelled) {
console.error('图像加载失败:', error);
console.error('图像URL:', canvasImage);
if (blob) {
const newUrl = URL.createObjectURL(blob);
console.log('从IndexedDB创建新的Blob URL:', newUrl);
// 更新canvasImage为新的URL
import('../store/useAppStore').then((storeModule) => {
const useAppStore = storeModule.useAppStore;
// 检查是否已取消
if (!isCancelled) {
useAppStore.getState().setCanvasImage(newUrl);
}
});
} else {
console.error('IndexedDB中未找到图像');
}
})
.catch(err => {
// 检查是否已取消
if (isCancelled) {
return;
}
console.error('从IndexedDB获取图像时出错:', err);
});
}).catch(err => {
// 检查是否已取消
if (isCancelled) {
return;
}
// 检查是否是Blob URL
if (canvasImage.startsWith('blob:')) {
console.log('正在检查Blob URL是否有效...');
console.error('导入referenceImageService时出错:', err);
});
}
// 检查是否是Blob URL
else if (canvasImage.startsWith('blob:')) {
console.log('正在检查Blob URL是否有效...');
// 尝试从AppStore重新获取Blob并创建新的URL
import('../store/useAppStore').then((module) => {
const useAppStore = module.useAppStore;
const blob = useAppStore.getState().getBlob(canvasImage);
if (blob) {
// 检查是否已取消
if (isCancelled) {
return;
}
// 检查Blob URL是否仍然有效
console.log('从AppStore找到Blob尝试重新创建URL...');
// 重新创建Blob URL并重试加载
const newUrl = URL.createObjectURL(blob);
console.log('创建新的Blob URL:', newUrl);
// 更新canvasImage为新的URL
useAppStore.getState().setCanvasImage(newUrl);
} else {
// 检查是否已取消
if (isCancelled) {
return;
}
console.error('AppStore中未找到Blob');
// 如果AppStore中也没有尝试通过fetch检查URL
fetch(canvasImage)
.then(response => {
// 检查是否已取消
if (isCancelled) {
return;
}
if (!response.ok) {
console.error('Blob URL无法访问:', response.status, response.statusText);
// 尝试从AppStore重新获取Blob并创建新的URL
import('../store/useAppStore').then((module) => {
const useAppStore = module.useAppStore;
const blob = useAppStore.getState().getBlob(canvasImage);
if (blob) {
console.log('从AppStore找到Blob尝试重新创建URL...');
// 重新创建Blob URL并重试加载
const newUrl = URL.createObjectURL(blob);
console.log('创建新的Blob URL:', newUrl);
// 更新canvasImage为新的URL
useAppStore.getState().setCanvasImage(newUrl);
} else {
console.error('AppStore中未找到Blob');
}
}).catch(err => {
console.error('导入AppStore时出错:', err);
});
} else {
console.log('Blob URL可以访问');
console.log('Blob URL可以访问,但图像加载仍然失败');
}
})
.catch(err => {
console.error('检查Blob URL时出错:', err);
// 尝试从AppStore重新获取Blob
import('../store/useAppStore').then((module) => {
const useAppStore = module.useAppStore;
const blob = useAppStore.getState().getBlob(canvasImage);
if (blob) {
console.log('从AppStore找到Blob尝试重新创建URL...');
// 重新创建Blob URL并重试加载
const newUrl = URL.createObjectURL(blob);
console.log('创建新的Blob URL:', newUrl);
// 更新canvasImage为新的URL
useAppStore.getState().setCanvasImage(newUrl);
} else {
console.error('AppStore中未找到Blob');
}
}).catch(err => {
console.error('导入AppStore时出错:', err);
});
.catch(fetchErr => {
// 检查是否已取消
if (isCancelled) {
return;
}
console.error('检查Blob URL时出错:', fetchErr);
});
}
}
};
img.src = canvasImage;
} else {
console.log('没有图像需要加载');
// 当没有图像时,清理之前的图像对象
if (image) {
// 清理图像对象以释放内存
image.onload = null;
image.onerror = null;
image.src = '';
}).catch(err => {
// 检查是否已取消
if (isCancelled) {
return;
}
console.error('导入AppStore时出错:', err);
});
}
setImage(null);
}
};
img.src = canvasImage;
// 清理函数
return () => {
console.log('清理图像加载资源');
// 标记为已取消
isCancelled = true;
// 取消图像加载
if (img) {
img.onload = null;
@@ -181,15 +245,8 @@ export const ImageCanvas: React.FC = () => {
// 清理图像源以释放内存
img.src = '';
}
// 清理之前的图像对象
if (image) {
image.onload = null;
image.onerror = null;
image.src = '';
}
};
}, [canvasImage, image, setCanvasZoom, stageSize.height, stageSize.width]); // 添加所有依赖项
}, [canvasImage, setCanvasZoom, setCanvasPan, stageSize.height, stageSize.width]); // 移除image依赖项
// 处理舞台大小调整
useEffect(() => {