CatPtain commited on
Commit
9ecdcee
·
verified ·
1 Parent(s): 1b0c279

Upload useExport.ts

Browse files
Files changed (1) hide show
  1. frontend/src/hooks/useExport.ts +105 -39
frontend/src/hooks/useExport.ts CHANGED
@@ -1156,12 +1156,20 @@ export default () => {
1156
  continue;
1157
  }
1158
 
1159
- // 检查元素尺寸
1160
  const dimensions = getElementDimensions(targetElement);
1161
  console.log(`Target element dimensions for ${el.id}:`, dimensions);
1162
 
1163
- if (dimensions.width <= 0 || dimensions.height <= 0) {
1164
- console.warn(`Invalid element dimensions for shape ${el.id}:`, dimensions);
 
 
 
 
 
 
 
 
1165
  console.log('Falling back to path-based export');
1166
  // 降级处理代码...
1167
  const scale = {
@@ -1204,52 +1212,111 @@ export default () => {
1204
  continue;
1205
  }
1206
 
1207
- // 使用Canvas渲染
1208
  let base64Image;
 
 
 
1209
  try {
1210
- console.log(`Starting Canvas rendering for ${el.id}`);
1211
-
1212
- // Canvas渲染选项
1213
- const renderOptions = {
1214
- scale: 2, // 高分辨率渲染
1215
- backgroundColor: null, // 透明背景
1216
- useCORS: true,
1217
- timeout: 10000, // 10秒超时
1218
- format: 'png' as const,
1219
- quality: 0.95
1220
- };
1221
 
1222
- base64Image = await renderElementToBase64(targetElement, renderOptions);
1223
-
1224
- console.log(`Canvas rendering result for ${el.id}:`, {
1225
- success: !!base64Image,
1226
- length: base64Image ? base64Image.length : 0,
1227
- preview: base64Image ? base64Image.substring(0, 100) + '...' : 'null'
1228
- });
1229
-
1230
- if (!base64Image || base64Image.length < 100) {
1231
- throw new Error('Canvas rendering returned empty or invalid result');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1232
  }
1233
- } catch (error) {
1234
- console.error(`Canvas rendering failed for shape ${el.id}:`, error);
1235
-
1236
- // 尝试SVG序列化作为备选方案
1237
- console.log(`Attempting SVG serialization fallback for ${el.id}`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1238
  try {
 
 
1239
  const svgElement = targetElement.tagName.toLowerCase() === 'svg'
1240
  ? targetElement
1241
  : targetElement.querySelector('svg');
1242
 
1243
  if (svgElement) {
1244
- base64Image = svg2Base64(svgElement);
1245
- console.log(`SVG fallback successful for ${el.id}`);
1246
- } else {
1247
- throw new Error('No SVG element found for fallback');
 
 
 
 
 
 
 
 
 
 
 
1248
  }
1249
- } catch (svgError) {
1250
- console.error(`SVG fallback also failed for ${el.id}:`, svgError);
1251
- // 最终降级到路径导出
1252
- console.log(`Final fallback to path-based export for ${el.id}`);
 
 
 
 
 
 
1253
  const scale = {
1254
  x: el.width / el.viewBox[0],
1255
  y: el.height / el.viewBox[1],
@@ -1288,7 +1355,6 @@ export default () => {
1288
 
1289
  pptxSlide.addShape('custGeom' as pptxgen.ShapeType, fallbackOptions);
1290
  continue;
1291
- }
1292
  }
1293
 
1294
  // 添加渲染后的图像到幻灯片
 
1156
  continue;
1157
  }
1158
 
1159
+ // 检查元素尺寸 - 使用更智能的检查逻辑
1160
  const dimensions = getElementDimensions(targetElement);
1161
  console.log(`Target element dimensions for ${el.id}:`, dimensions);
1162
 
1163
+ // 更宽松的尺寸检查:只要有任何一种尺寸测量方法返回有效值就继续
1164
+ const hasValidDimensions = (
1165
+ dimensions.width > 0 || dimensions.height > 0 ||
1166
+ dimensions.clientWidth > 0 || dimensions.clientHeight > 0 ||
1167
+ dimensions.offsetWidth > 0 || dimensions.offsetHeight > 0 ||
1168
+ dimensions.boundingRect.width > 0 || dimensions.boundingRect.height > 0
1169
+ );
1170
+
1171
+ if (!hasValidDimensions) {
1172
+ console.warn(`No valid dimensions found for shape ${el.id}:`, dimensions);
1173
  console.log('Falling back to path-based export');
1174
  // 降级处理代码...
1175
  const scale = {
 
1212
  continue;
1213
  }
1214
 
1215
+ // 使用多重策略渲染矢量图形
1216
  let base64Image;
1217
+ let renderSuccess = false;
1218
+
1219
+ // 策略1: 优先使用SVG序列化(对矢量图形更可靠)
1220
  try {
1221
+ console.log(`Attempting SVG serialization for ${el.id}`);
 
 
 
 
 
 
 
 
 
 
1222
 
1223
+ const svgElement = targetElement.tagName.toLowerCase() === 'svg'
1224
+ ? targetElement
1225
+ : targetElement.querySelector('svg');
1226
+
1227
+ if (svgElement) {
1228
+ // 确保SVG元素已完全渲染
1229
+ await new Promise(resolve => {
1230
+ requestAnimationFrame(() => {
1231
+ requestAnimationFrame(resolve);
1232
+ });
1233
+ });
1234
+
1235
+ base64Image = svg2Base64(svgElement);
1236
+
1237
+ console.log(`SVG serialization result for ${el.id}:`, {
1238
+ success: !!base64Image,
1239
+ length: base64Image ? base64Image.length : 0,
1240
+ preview: base64Image ? base64Image.substring(0, 100) + '...' : 'null'
1241
+ });
1242
+
1243
+ if (base64Image && base64Image.length > 100) {
1244
+ renderSuccess = true;
1245
+ console.log(`SVG serialization successful for ${el.id}`);
1246
+ }
1247
  }
1248
+ } catch (svgError) {
1249
+ console.warn(`SVG serialization failed for ${el.id}:`, svgError);
1250
+ }
1251
+
1252
+ // 策略2: 如果SVG序列化失败,使用Canvas渲染
1253
+ if (!renderSuccess) {
1254
+ try {
1255
+ console.log(`Attempting Canvas rendering for ${el.id}`);
1256
+
1257
+ // Canvas渲染选项
1258
+ const renderOptions = {
1259
+ scale: 2, // 高分辨率渲染
1260
+ backgroundColor: null, // 透明背景
1261
+ useCORS: true,
1262
+ timeout: 15000, // 增加超时时间
1263
+ format: 'png' as const,
1264
+ quality: 0.95
1265
+ };
1266
+
1267
+ base64Image = await renderElementToBase64(targetElement, renderOptions);
1268
+
1269
+ console.log(`Canvas rendering result for ${el.id}:`, {
1270
+ success: !!base64Image,
1271
+ length: base64Image ? base64Image.length : 0,
1272
+ preview: base64Image ? base64Image.substring(0, 100) + '...' : 'null'
1273
+ });
1274
+
1275
+ if (base64Image && base64Image.length > 100) {
1276
+ renderSuccess = true;
1277
+ console.log(`Canvas rendering successful for ${el.id}`);
1278
+ }
1279
+ } catch (canvasError) {
1280
+ console.error(`Canvas rendering failed for ${el.id}:`, canvasError);
1281
+ }
1282
+ }
1283
+
1284
+ // 策略3: 如果前两种方法都失败,尝试简化的SVG渲染
1285
+ if (!renderSuccess) {
1286
  try {
1287
+ console.log(`Attempting simplified SVG rendering for ${el.id}`);
1288
+
1289
  const svgElement = targetElement.tagName.toLowerCase() === 'svg'
1290
  ? targetElement
1291
  : targetElement.querySelector('svg');
1292
 
1293
  if (svgElement) {
1294
+ // 创建简化的SVG副本
1295
+ const simplifiedSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
1296
+ const rect = svgElement.getBoundingClientRect();
1297
+
1298
+ simplifiedSVG.setAttribute('width', (rect.width || 100).toString());
1299
+ simplifiedSVG.setAttribute('height', (rect.height || 100).toString());
1300
+ simplifiedSVG.setAttribute('viewBox', `0 0 ${rect.width || 100} ${rect.height || 100}`);
1301
+ simplifiedSVG.innerHTML = svgElement.innerHTML;
1302
+
1303
+ base64Image = svg2Base64(simplifiedSVG);
1304
+
1305
+ if (base64Image && base64Image.length > 100) {
1306
+ renderSuccess = true;
1307
+ console.log(`Simplified SVG rendering successful for ${el.id}`);
1308
+ }
1309
  }
1310
+ } catch (simplifiedError) {
1311
+ console.error(`Simplified SVG rendering failed for ${el.id}:`, simplifiedError);
1312
+ }
1313
+ }
1314
+
1315
+ // 如果所有渲染策略都失败,使用路径导出作为最后备选
1316
+ if (!renderSuccess) {
1317
+ console.warn(`All rendering strategies failed for ${el.id}, falling back to path export`);
1318
+ // 最终降级到路径导出
1319
+ console.log(`Final fallback to path-based export for ${el.id}`);
1320
  const scale = {
1321
  x: el.width / el.viewBox[0],
1322
  y: el.height / el.viewBox[1],
 
1355
 
1356
  pptxSlide.addShape('custGeom' as pptxgen.ShapeType, fallbackOptions);
1357
  continue;
 
1358
  }
1359
 
1360
  // 添加渲染后的图像到幻灯片