Upload public.js
Browse files- backend/src/routes/public.js +117 -56
backend/src/routes/public.js
CHANGED
@@ -19,8 +19,10 @@ const generateSlideHTML = (pptData, slideIndex, title) => {
|
|
19 |
const slide = pptData.slides[slideIndex];
|
20 |
const theme = pptData.theme || {};
|
21 |
|
22 |
-
// 精确计算PPT内容的真实尺寸 -
|
23 |
const calculatePptDimensions = (slide) => {
|
|
|
|
|
24 |
// 1. 优先使用PPT数据中的viewportSize和viewportRatio(编辑器的真实尺寸)
|
25 |
if (pptData.viewportSize && pptData.viewportRatio) {
|
26 |
const result = {
|
@@ -61,65 +63,124 @@ const generateSlideHTML = (pptData, slideIndex, title) => {
|
|
61 |
return result;
|
62 |
}
|
63 |
|
64 |
-
// 5.
|
65 |
-
if (
|
66 |
-
//
|
67 |
-
const
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
let minLeft = Infinity;
|
75 |
-
let minTop = Infinity;
|
76 |
-
|
77 |
-
// 计算所有元素的实际边界
|
78 |
-
slide.elements.forEach(element => {
|
79 |
-
const left = element.left || 0;
|
80 |
-
const top = element.top || 0;
|
81 |
-
const width = element.width || 0;
|
82 |
-
const height = element.height || 0;
|
83 |
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
}
|
115 |
|
116 |
-
//
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
const result = { width: finalWidth, height: finalHeight };
|
121 |
-
console.log(`根据元素计算尺寸: ${result.width}x${result.height}`);
|
122 |
-
|
123 |
return result;
|
124 |
};
|
125 |
|
|
|
19 |
const slide = pptData.slides[slideIndex];
|
20 |
const theme = pptData.theme || {};
|
21 |
|
22 |
+
// 精确计算PPT内容的真实尺寸 - 基于填满画布的图像元素推断
|
23 |
const calculatePptDimensions = (slide) => {
|
24 |
+
console.log('开始计算PPT尺寸,当前slide元素数量:', slide.elements?.length || 0);
|
25 |
+
|
26 |
// 1. 优先使用PPT数据中的viewportSize和viewportRatio(编辑器的真实尺寸)
|
27 |
if (pptData.viewportSize && pptData.viewportRatio) {
|
28 |
const result = {
|
|
|
63 |
return result;
|
64 |
}
|
65 |
|
66 |
+
// 5. 基于填满画布的图像元素精确推断PPT尺寸
|
67 |
+
if (slide.elements && slide.elements.length > 0) {
|
68 |
+
// 寻找可能填满画布的图像元素(left=0, top=0 或接近0,且尺寸较大)
|
69 |
+
const candidateImages = slide.elements.filter(element =>
|
70 |
+
element.type === 'image' &&
|
71 |
+
Math.abs(element.left || 0) <= 10 && // 允许小偏差
|
72 |
+
Math.abs(element.top || 0) <= 10 && // 允许小偏差
|
73 |
+
(element.width || 0) >= 800 && // 宽度至少800
|
74 |
+
(element.height || 0) >= 400 // 高度至少400
|
75 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
+
if (candidateImages.length > 0) {
|
78 |
+
// 使用面积最大的图像作为画布尺寸参考
|
79 |
+
const referenceImage = candidateImages.reduce((max, current) => {
|
80 |
+
const maxArea = (max.width || 0) * (max.height || 0);
|
81 |
+
const currentArea = (current.width || 0) * (current.height || 0);
|
82 |
+
return currentArea > maxArea ? current : max;
|
83 |
+
});
|
84 |
+
|
85 |
+
const result = {
|
86 |
+
width: Math.ceil(referenceImage.width || 1000),
|
87 |
+
height: Math.ceil(referenceImage.height || 562)
|
88 |
+
};
|
89 |
+
|
90 |
+
console.log(`基于填满画布的图像推断PPT尺寸: ${result.width}x${result.height} (参考图像: ${referenceImage.id})`);
|
91 |
+
console.log(`参考图像信息: left=${referenceImage.left}, top=${referenceImage.top}, width=${referenceImage.width}, height=${referenceImage.height}`);
|
92 |
+
|
93 |
+
return result;
|
94 |
+
}
|
95 |
|
96 |
+
// 如果没有找到填满画布的图像,回退到边界计算
|
97 |
+
let maxRight = 0;
|
98 |
+
let maxBottom = 0;
|
99 |
+
let minLeft = Infinity;
|
100 |
+
let minTop = Infinity;
|
101 |
+
|
102 |
+
// 计算所有元素的实际边界
|
103 |
+
slide.elements.forEach(element => {
|
104 |
+
const left = element.left || 0;
|
105 |
+
const top = element.top || 0;
|
106 |
+
const width = element.width || 0;
|
107 |
+
const height = element.height || 0;
|
108 |
+
|
109 |
+
const elementRight = left + width;
|
110 |
+
const elementBottom = top + height;
|
111 |
+
|
112 |
+
maxRight = Math.max(maxRight, elementRight);
|
113 |
+
maxBottom = Math.max(maxBottom, elementBottom);
|
114 |
+
minLeft = Math.min(minLeft, left);
|
115 |
+
minTop = Math.min(minTop, top);
|
116 |
+
|
117 |
+
console.log(`元素 ${element.id}: type=${element.type}, left=${left}, top=${top}, width=${width}, height=${height}, right=${elementRight}, bottom=${elementBottom}`);
|
118 |
+
});
|
119 |
+
|
120 |
+
// 重置无限值
|
121 |
+
if (minLeft === Infinity) minLeft = 0;
|
122 |
+
if (minTop === Infinity) minTop = 0;
|
123 |
+
|
124 |
+
console.log(`元素边界: minLeft=${minLeft}, minTop=${minTop}, maxRight=${maxRight}, maxBottom=${maxBottom}`);
|
125 |
+
|
126 |
+
// 根据实际元素分布确定画布尺寸
|
127 |
+
const canvasLeft = Math.min(0, minLeft);
|
128 |
+
const canvasTop = Math.min(0, minTop);
|
129 |
+
const canvasRight = Math.max(maxRight, 1000); // 最小宽度1000(基于GitHub数据)
|
130 |
+
const canvasBottom = Math.max(maxBottom, 562); // 最小高度562(基于GitHub数据)
|
131 |
+
|
132 |
+
// 计算最终的画布尺寸
|
133 |
+
let finalWidth = canvasRight - canvasLeft;
|
134 |
+
let finalHeight = canvasBottom - canvasTop;
|
135 |
+
|
136 |
+
// 基于从GitHub仓库观察到的实际比例进行智能调整
|
137 |
+
const currentRatio = finalWidth / finalHeight;
|
138 |
+
console.log(`当前计算比例: ${currentRatio.toFixed(3)}`);
|
139 |
+
|
140 |
+
// 从GitHub数据分析:1000x562.5 ≈ 1.78 (接近16:9的1.77)
|
141 |
+
const targetRatio = 1000 / 562.5; // ≈ 1.778
|
142 |
+
|
143 |
+
// 如果比例接近观察到的标准比例,调整为精确比例
|
144 |
+
if (Math.abs(currentRatio - targetRatio) < 0.2) {
|
145 |
+
if (finalWidth > finalHeight * targetRatio) {
|
146 |
+
finalHeight = finalWidth / targetRatio;
|
147 |
+
} else {
|
148 |
+
finalWidth = finalHeight * targetRatio;
|
149 |
+
}
|
150 |
+
console.log(`调整为GitHub观察到的标准比例: ${targetRatio.toFixed(3)}`);
|
151 |
+
}
|
152 |
+
// 如果比例接近16:9,调整为标准16:9
|
153 |
+
else if (Math.abs(currentRatio - 16/9) < 0.1) {
|
154 |
+
if (finalWidth > finalHeight * 16/9) {
|
155 |
+
finalHeight = finalWidth / (16/9);
|
156 |
+
} else {
|
157 |
+
finalWidth = finalHeight * (16/9);
|
158 |
+
}
|
159 |
+
console.log(`调整为16:9比例`);
|
160 |
+
}
|
161 |
+
// 如果比例接近4:3,调整为标准4:3
|
162 |
+
else if (Math.abs(currentRatio - 4/3) < 0.1) {
|
163 |
+
if (finalWidth > finalHeight * 4/3) {
|
164 |
+
finalHeight = finalWidth / (4/3);
|
165 |
+
} else {
|
166 |
+
finalWidth = finalHeight * (4/3);
|
167 |
+
}
|
168 |
+
console.log(`调整为4:3比例`);
|
169 |
+
}
|
170 |
+
|
171 |
+
// 确保尺寸为偶数(避免半像素问题)
|
172 |
+
finalWidth = Math.ceil(finalWidth / 2) * 2;
|
173 |
+
finalHeight = Math.ceil(finalHeight / 2) * 2;
|
174 |
+
|
175 |
+
const result = { width: finalWidth, height: finalHeight };
|
176 |
+
console.log(`根据元素边界计算最终尺寸: ${result.width}x${result.height}, 比例: ${(result.width/result.height).toFixed(3)}`);
|
177 |
+
|
178 |
+
return result;
|
179 |
}
|
180 |
|
181 |
+
// 6. 如果没有元素,使用从GitHub数据分析得出的标准尺寸
|
182 |
+
const result = { width: 1000, height: 562 }; // 基于GitHub仓库中观察到的实际数据
|
183 |
+
console.log(`使用GitHub数据分析的默认尺寸: ${result.width}x${result.height} (1000x562, 比例≈1.78)`);
|
|
|
|
|
|
|
|
|
184 |
return result;
|
185 |
};
|
186 |
|