fix: 封面设计 720p 预览与导出

- loadBackground 居中改用 canvas.width/height,适配动态分辨率
- renderCover 修改 Canvas 内部尺寸后重设 CSS 预览尺寸,避免 overflow:hidden 裁剪内容
- 恢复 CoverDesign.tsx exportPng() 无参调用,匹配 hook 签名
This commit is contained in:
小鱼开发
2026-06-05 18:47:42 +08:00
parent 4e807525e9
commit d161fc95a8
2 changed files with 25 additions and 14 deletions
+24 -13
View File
@@ -200,18 +200,20 @@ export function useCoverFabric() {
}
const fabricImg = new FabricImage(img);
const cw = canvas.width ?? CANVAS_WIDTH;
const ch = canvas.height ?? CANVAS_HEIGHT;
// 使用 Math.min 确保图片完整显示在 Canvas 内,不会被过度放大
const scale = Math.min(
CANVAS_WIDTH / (fabricImg.width || 1),
CANVAS_HEIGHT / (fabricImg.height || 1)
cw / (fabricImg.width || 1),
ch / (fabricImg.height || 1)
);
fabricImg.scale(scale);
// 居中定位
// 居中定位(按 Canvas 当前实际尺寸)
const scaledWidth = (fabricImg.width || 1) * scale;
const scaledHeight = (fabricImg.height || 1) * scale;
fabricImg.set({
left: (CANVAS_WIDTH - scaledWidth) / 2,
top: (CANVAS_HEIGHT - scaledHeight) / 2,
left: (cw - scaledWidth) / 2,
top: (ch - scaledHeight) / 2,
originX: 'left',
originY: 'top',
selectable: false,
@@ -284,10 +286,20 @@ export function useCoverFabric() {
await loadCustomFont().catch(() => {
});
// Canvas 内部渲染尺寸始终保持 1080×1920 不变,
// 通过 resolutionScale 缩放所有元素,避免 Fabric.js 尺寸突变导致文字错乱。
// CSS 显示尺寸由 initCanvas 固定为 337×600,不受此处影响。
void targetHeight; // 保留接口兼容性,实际通过 multiplier 在导出时处理高度
// 调整 canvas 内部渲染尺寸以匹配目标分辨率
if (canvas.width !== targetWidth || canvas.height !== targetHeight) {
canvas.setDimensions(
{ width: targetWidth, height: targetHeight },
{ cssOnly: false }
);
// 重新固定 CSS 预览尺寸,防止 Fabric.js 把 CSS 也改成目标分辨率
// 导致容器 overflow:hidden 把内容裁掉
canvas.setDimensions(
{ width: DISPLAY_WIDTH, height: DISPLAY_HEIGHT },
{ cssOnly: true }
);
}
const resolutionScale = targetWidth / CANVAS_WIDTH;
canvas.clear();
@@ -388,12 +400,11 @@ export function useCoverFabric() {
[loadBackground, loadAvatarImage]
);
// 导出 PNG(通过 multiplier 缩放到目标分辨率)
const exportPng = useCallback((targetWidth?: number): string => {
// 导出 PNG
const exportPng = useCallback((): string => {
const canvas = fabricCanvasRef.current;
if (!canvas) {return '';}
const multiplier = (targetWidth ?? CANVAS_WIDTH) / CANVAS_WIDTH;
return canvas.toDataURL({ format: 'png', quality: 1, multiplier });
return canvas.toDataURL({ format: 'png', quality: 1, multiplier: 1 });
}, []);
// 销毁
@@ -332,7 +332,7 @@ export default function CoverDesign() {
}
}
const dataUrl = exportPng(videoResolution?.width);
const dataUrl = exportPng();
if (!dataUrl) {
throw new Error('封面设计失败');
}